6f8dd96818abbfd1fb3b02621f7bdf916f0d4f64
[platform/upstream/lsof.git] / dialects / freebsd / dsock.c
1 /*
2  * dsock.c - FreeBSD socket processing functions for lsof
3  */
4
5
6 /*
7  * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
8  * 47907.  All rights reserved.
9  *
10  * Written by Victor A. Abell
11  *
12  * This software is not subject to any license of the American Telephone
13  * and Telegraph Company or the Regents of the University of California.
14  *
15  * Permission is granted to anyone to use this software for any purpose on
16  * any computer system, and to alter it and redistribute it freely, subject
17  * to the following restrictions:
18  *
19  * 1. Neither the authors nor Purdue University are responsible for any
20  *    consequences of the use of this software.
21  *
22  * 2. The origin of this software must not be misrepresented, either by
23  *    explicit claim or by omission.  Credit to the authors and Purdue
24  *    University must appear in documentation and sources.
25  *
26  * 3. Altered versions must be plainly marked as such, and must not be
27  *    misrepresented as being the original software.
28  *
29  * 4. This notice may not be removed or altered.
30  */
31
32 #ifndef lint
33 static char copyright[] =
34 "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35 static char *rcsid = "$Id: dsock.c,v 1.29 2013/01/02 17:01:43 abe Exp $";
36 #endif
37
38
39 #include "lsof.h"
40
41
42 #if     defined(HASIPv6)
43
44 /*
45  * IPv6_2_IPv4()  -- macro to define the address of an IPv4 address contained
46  *                   in an IPv6 address
47  */
48
49 #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
50
51 # if    defined(HAS_NO_6PORT)
52 /*
53  * If the in_pcb structure no longer has the KAME accommodations of
54  * in6p_[fl]port, redefine them to inp_[fl]port.
55  */
56
57 #define in6p_fport      inp_fport
58 #define in6p_lport      inp_lport
59 # endif /* defined(HAS_NO_6PORT) */
60
61 # if    defined(HAS_NO_6PPCB)
62 /*
63  * If the in_pcb structure no longer has the KAME accommodation of in6p_pcb,
64  * redefine it to inp_ppcb.
65  */
66
67 #define in6p_ppcb       inp_ppcb
68 # endif /* defined(HAS_NO_6PPCB) */
69 #endif  /* defined(HASIPv6) */
70
71
72 /*
73  * Local function prototypes
74  */
75
76 _PROTOTYPE(static int ckstate,(KA_T ta, struct tcpcb *t, int fam));
77
78
79 /*
80  * ckstate() -- read TCP control block and check TCP state for inclusion
81  *              or exclusion
82  * return: -1 == no TCP CB available
83  *          0 == TCP DB available; continue processing file
84  *          1 == stop processing file
85  */
86
87 static int
88 ckstate(ta, t, fam)
89         KA_T ta;                        /* TCP control block address */
90         struct tcpcb *t;                /* TCP control block receptor */
91         int fam;                        /* protocol family */
92 {
93         int tsnx;
94 /*
95  * Read TCP control block.
96  */
97         if (kread(ta, (char *)t, sizeof(struct tcpcb)))
98             return(-1);
99         if (TcpStXn || TcpStIn) {
100
101         /*
102          * If there are TCP state inclusions or exclusions, check them.
103          */
104             tsnx = (int)t->t_state + TcpStOff;
105             if (TcpStXn) {
106                 if (TcpStX[tsnx]) {
107                     Lf->sf &= ~SELNET;
108                     Lf->sf |= SELEXCLF;
109                     return(1);
110                 }
111             }
112             if (TcpStIn) {
113                 if (TcpStI[tsnx]) {
114                     TcpStI[tsnx] = 2;
115                     Lf->sf |= SELNET;
116                 } else {
117                     Lf->sf &= ~SELNET;
118                     Lf->sf |= SELEXCLF;
119                     return(1);
120                 }
121             }
122         }
123         if (!(Lf->sf & SELNET) && !TcpStIn) {
124
125         /*
126          * See if this TCP file should be selected.
127          */
128             if (Fnet) {
129                 if (!FnetTy
130                 ||  ((FnetTy == 4) && (fam == AF_INET))
131
132 #if     defined(HASIPv6)
133                 ||  ((FnetTy == 6) && (fam == AF_INET6))
134 #endif  /* defined(HASIPv6) */
135
136                 ) {
137                     Lf->sf |= SELNET;
138                 }
139             }
140         }
141         return(0);
142 }
143
144
145 /*
146  * process_socket() - process socket
147  */
148
149 void
150 process_socket(sa)
151         KA_T sa;                        /* socket address in kernel */
152 {
153         struct domain d;
154         unsigned char *fa = (unsigned char *)NULL;
155         int fam;
156         int fp, lp;
157         struct inpcb inp;
158         unsigned char *la = (unsigned char *)NULL;
159         struct protosw p;
160         struct socket s;
161         struct tcpcb t;
162         int ts = -1;
163         struct unpcb uc, unp;
164         struct sockaddr_un *ua = NULL;
165         struct sockaddr_un un;
166
167 #if     FREEBSDV<4050
168         struct mbuf mb;
169 #else   /* FREEBSDV>=4050 */
170         int unl;
171 #endif  /* FREEBSDV<4050 */
172
173 #if     defined(HASIPv6) && !defined(HASINRIAIPv6)
174         struct in6pcb in6p;
175 #endif  /* defined(HASIPv6) && !defined(HASINRIAIPv6) */
176
177         (void) snpf(Lf->type, sizeof(Lf->type), "sock");
178         Lf->inp_ty = 2;
179 /*
180  * Read the socket, protocol, and domain structures.
181  */
182         if (!sa) {
183             enter_nm("no socket address");
184             return;
185         }
186         if (kread(sa, (char *) &s, sizeof(s))) {
187             (void) snpf(Namech, Namechl, "can't read socket struct from %s",
188                 print_kptr(sa, (char *)NULL, 0));
189             enter_nm(Namech);
190             return;
191         }
192         if (!s.so_type) {
193             enter_nm("no socket type");
194             return;
195         }
196         if (!s.so_proto
197         ||  kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
198             (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
199                 print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
200             enter_nm(Namech);
201             return;
202         }
203         if (!p.pr_domain
204         ||  kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
205             (void) snpf(Namech, Namechl, "can't read domain struct from %s",
206                 print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
207             enter_nm(Namech);
208             return;
209         }
210 /*
211  * Save size information.
212  */
213         if (Fsize) {
214             if (Lf->access == 'r')
215                 Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
216             else if (Lf->access == 'w')
217                 Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
218             else
219                 Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
220             Lf->sz_def = 1;
221         } else
222             Lf->off_def = 1;
223
224 #if     defined(HASTCPTPIQ)
225         Lf->lts.rq = s.so_rcv.sb_cc;
226         Lf->lts.sq = s.so_snd.sb_cc;
227         Lf->lts.rqs = Lf->lts.sqs = 1;
228 #endif  /* defined(HASTCPTPIQ) */
229
230 #if     defined(HASSOOPT)
231         Lf->lts.ltm = (unsigned int)s.so_linger;
232         Lf->lts.opt = (unsigned int)s.so_options;
233         Lf->lts.pqlen = (unsigned int)s.so_incqlen;
234         Lf->lts.qlen = (unsigned int)s.so_qlen;
235         Lf->lts.qlim = (unsigned int)s.so_qlimit;
236         Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
237         Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
238         Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
239                        = Lf->lts.sbszs = (unsigned char)1;
240 #endif  /* defined(HASSOOPT) */
241
242 #if     defined(HASSOSTATE)
243         Lf->lts.ss = (unsigned int)s.so_state;
244 # if    defined(HASSBSTATE)
245         Lf->lts.sbs_rcv = s.so_rcv.sb_state;
246         Lf->lts.sbs_snd = s.so_snd.sb_state;
247 # endif /* defined(HASSBSTATE) */
248 #endif  /* defined(HASSOSTATE) */
249
250 /*
251  * Process socket by the associated domain family.
252  */
253         switch ((fam = d.dom_family)) {
254 /*
255  * Process an Internet domain socket.
256  */
257         case AF_INET:
258
259 #if     defined(HASIPv6)
260         case AF_INET6:
261 #endif  /* defined(HASIPv6) */
262
263             if (Fnet) {
264                 if (!FnetTy
265                 ||  ((FnetTy == 4) && (fam == AF_INET))
266
267 #if     defined(HASIPv6)
268                 ||  ((FnetTy == 6) && (fam == AF_INET6))
269 #endif  /* defined(HASIPv6) */
270
271                 ) {
272                     if (!TcpStIn && !UdpStIn)
273                         Lf->sf |= SELNET;
274                 }
275             }
276             printiproto(p.pr_protocol);
277
278 #if     defined(HASIPv6)
279             (void) snpf(Lf->type, sizeof(Lf->type),
280                 (fam == AF_INET) ? "IPv4" : "IPv6");
281 #else   /* !defined(HASIPv6) */
282             (void) snpf(Lf->type, sizeof(Lf->type), "inet");
283 #endif  /* defined(HASIPv6) */
284
285 #if     defined(HASIPv6) && !defined(HASINRIAIPv6)
286             if (fam == AF_INET6) {
287
288             /*
289              * Read IPv6 protocol control block.
290              */
291                 if (!s.so_pcb
292                 ||  kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) {
293                     (void) snpf(Namech, Namechl, "can't read in6pcb at %s",
294                         print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
295                     enter_nm(Namech);
296                     return;
297                 }
298             /*
299              * Save IPv6 address information.
300              */
301                 if (p.pr_protocol == IPPROTO_TCP) {
302                     if (in6p.in6p_ppcb) {
303                         if ((ts = ckstate((KA_T)in6p.in6p_ppcb, &t, fam)) == 1)
304                             return;
305                     }
306                 }
307                 enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb
308                                                               : s.so_pcb),
309                                                (char *)NULL, 0));
310                 la = (unsigned char *)&in6p.in6p_laddr;
311                 lp = (int)ntohs(in6p.in6p_lport);
312                 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr)
313                 ||  in6p.in6p_fport)
314                 {
315                     fa = (unsigned char *)&in6p.in6p_faddr;
316                     fp = (int)ntohs(in6p.in6p_fport);
317                 }
318             } else
319 #endif  /* defined(HASIPv6) && !defined(HASINRIAIPv6) */
320
321             {
322
323             /*
324              * Read Ipv4 or IPv6 (INRIA) protocol control block.
325              */
326                 if (!s.so_pcb
327                 ||  kread((KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) {
328                     if (!s.so_pcb) {
329                         (void) snpf(Namech, Namechl, "no PCB%s%s",
330
331 #if     defined(HASSBSTATE)
332                             (s.so_snd.sb_state & SBS_CANTSENDMORE) ?
333 #else   /* !defined(HASSBSTATE) */
334                             (s.so_state & SS_CANTSENDMORE) ?
335 #endif  /* defined(HASSBSTATE) */ 
336
337                                 ", CANTSENDMORE" : "",
338 #if     defined(HASSBSTATE)
339                             (s.so_rcv.sb_state & SBS_CANTRCVMORE) ?
340 #else   /* !defined(HASSBSTATE) */
341                             (s.so_state & SS_CANTRCVMORE) ?
342 #endif  /* defined(HASSBSTATE) */
343
344                                 ", CANTRCVMORE" : "");
345                     } else {
346                         (void) snpf(Namech, Namechl, "can't read inpcb at %s",
347                             print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
348                     }
349                     enter_nm(Namech);
350                     return;
351                 }
352                 if (p.pr_protocol == IPPROTO_TCP) {
353                     if (inp.inp_ppcb) {
354                         if ((ts = ckstate((KA_T)inp.inp_ppcb, &t, fam)) == 1)
355                             return;
356                     }
357                 }
358                 enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
359                                                             : s.so_pcb),
360                                                (char *)NULL, 0));
361                 lp = (int)ntohs(inp.inp_lport);
362                 if (fam == AF_INET) {
363
364                 /*
365                  * Save IPv4 address information.
366                  */
367                     la = (unsigned char *)&inp.inp_laddr;
368                     if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) {
369                         fa = (unsigned char *)&inp.inp_faddr;
370                         fp = (int)ntohs(inp.inp_fport);
371                     }
372                 }
373                 
374 #if     defined(HASIPv6) && defined(HASINRIAIPv6)
375                 else {
376                     la = (unsigned char *)&inp.inp_laddr6;
377                     if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)
378                     ||  inp.inp_fport)
379                     {
380                         fa = (unsigned char *)&inp.inp_faddr6;
381                         fp = (int)ntohs(inp.inp_fport);
382                     }
383                 }
384 #endif  /* defined(HASIPv6) && defined(HASINRIAIPv6) */
385
386             }
387
388
389 #if     defined(HASIPv6)
390             if ((fam == AF_INET6)
391             &&  ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
392             ||  ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) {
393
394             /*
395              * Adjust for IPv4 addresses mapped in IPv6 addresses.
396              */
397                 if (la)
398                     la = (unsigned char *)IPv6_2_IPv4(la);
399                 if (fa)
400                     fa = (unsigned char *)IPv6_2_IPv4(fa);
401                 fam = AF_INET;
402             }
403 #endif  /* defined(HASIPv6) */
404
405         /*
406          * Enter local and remote addresses by address family.
407          */
408             if (fa || la)
409                 (void) ent_inaddr(la, lp, fa, fp, fam);
410             if (ts == 0) {
411                 Lf->lts.type = 0;
412                 Lf->lts.state.i = (int)t.t_state;
413
414 #if     defined(HASTCPOPT)
415                 Lf->lts.mss = (unsigned long)t.t_maxseg;
416                 Lf->lts.msss = (unsigned char)1;
417                 Lf->lts.topt = (unsigned int)t.t_flags;
418 #endif  /* defined(HASTCPOPT) */
419
420             }
421             break;
422 /*
423  * Process a ROUTE domain socket.
424  */
425         case AF_ROUTE:
426             (void) snpf(Lf->type, sizeof(Lf->type), "rte");
427             if (s.so_pcb)
428                 enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
429             else
430                 (void) snpf(Namech, Namechl, "no protocol control block");
431             if (!Fsize)
432                 Lf->off_def = 1;
433             break;
434 /*
435  * Process a Unix domain socket.
436  */
437         case AF_UNIX:
438             if (Funix)
439                 Lf->sf |= SELUNX;
440             (void) snpf(Lf->type, sizeof(Lf->type), "unix");
441         /*
442          * Read Unix protocol control block and the Unix address structure.
443          */
444
445             enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
446             if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
447                 (void) snpf(Namech, Namechl, "can't read unpcb at %s",
448                     print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
449                 break;
450             }
451             if ((struct socket *)sa != unp.unp_socket) {
452                 (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
453                     print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
454                 break;
455             }
456             if (unp.unp_addr) {
457
458 #if     FREEBSDV<4050
459                 if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)))
460 #else   /* FREEBSDV>=4050 */
461                 if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un)))
462 #endif  /* FREEBSDV<4050 */
463
464                 {
465                     (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
466                         print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
467                     break;
468                 }
469
470 #if     FREEBSDV<4050
471                 if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un))
472                     ua = (struct sockaddr_un *) ((char *) &mb
473                        + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr));
474 #else   /* FREEBSDV>=4050 */
475                 ua = &un;
476 #endif  /* FREEBSDV<4050 */
477
478             }
479             if (!ua) {
480                 ua = &un;
481                 (void) bzero((char *)ua, sizeof(un));
482                 ua->sun_family = AF_UNSPEC;
483             }
484         /*
485          * Print information on Unix socket that has no address bound
486          * to it, although it may be connected to another Unix domain
487          * socket as a pipe.
488          */
489             if (ua->sun_family != AF_UNIX) {
490                 if (ua->sun_family == AF_UNSPEC) {
491                     if (unp.unp_conn) {
492                         if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
493                             (void) snpf(Namech, Namechl,
494                                 "can't read unp_conn at %s",
495                                 print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
496                         else
497                             (void) snpf(Namech, Namechl, "->%s",
498                                 print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
499                     } else
500                         (void) snpf(Namech, Namechl, "->(none)");
501                 } else
502                     (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
503                         ua->sun_family);
504                 break;
505             }
506             if (ua->sun_path[0]) {
507
508 #if     FREEBSDV<4050
509                 if (mb.m_len >= sizeof(struct sockaddr_un))
510                     mb.m_len = sizeof(struct sockaddr_un) - 1;
511                 *((char *)ua + mb.m_len) = '\0';
512 #else   /* FREEBSDV>=4050 */
513 # if    FREEBSDV>4060
514                 unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path);
515 # else  /* FREEBSDV<4060 */
516                 unl = sizeof(ua->sun_path) - 1;
517 # endif /* FREEBSDV>4060 */ 
518                 if ((unl < 0) || (unl >= sizeof(ua->sun_path)))
519                     unl = sizeof(ua->sun_path) - 1;
520                 ua->sun_path[unl] = '\0';
521 #endif  /* FREEBSDV<4050 */
522
523                 if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0))
524                     Lf->sf |= SELNM;
525                 if (ua->sun_path[0] && !Namech[0])
526                     (void) snpf(Namech, Namechl, "%s", ua->sun_path);
527             } else
528                 (void) snpf(Namech, Namechl, "no address");
529             break;
530         default:
531             printunkaf(fam, 1);
532         }
533         if (Namech[0])
534             enter_nm(Namech);
535 }