]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/raw_ip.c
This commit was generated by cvs2svn to compensate for changes in r78460,
[FreeBSD/FreeBSD.git] / sys / netinet / raw_ip.c
1 /*
2  * Copyright (c) 1982, 1986, 1988, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      @(#)raw_ip.c    8.7 (Berkeley) 5/15/95
34  * $FreeBSD$
35  */
36
37 #include "opt_inet6.h"
38 #include "opt_ipsec.h"
39 #include "opt_random_ip_id.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/sysctl.h>
50
51 #include <vm/vm_zone.h>
52
53 #include <net/if.h>
54 #include <net/route.h>
55
56 #define _IP_VHL
57 #include <netinet/in.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/ip.h>
60 #include <netinet/in_pcb.h>
61 #include <netinet/in_var.h>
62 #include <netinet/ip_var.h>
63 #include <netinet/ip_mroute.h>
64
65 #include <netinet/ip_fw.h>
66
67 #ifdef IPSEC
68 #include <netinet6/ipsec.h>
69 #endif /*IPSEC*/
70
71 #include "opt_ipdn.h"
72 #ifdef DUMMYNET
73 #include <netinet/ip_dummynet.h>
74 #endif
75
76 struct  inpcbhead ripcb;
77 struct  inpcbinfo ripcbinfo;
78
79 /*
80  * Nominal space allocated to a raw ip socket.
81  */
82 #define RIPSNDQ         8192
83 #define RIPRCVQ         8192
84
85 /*
86  * Raw interface to IP protocol.
87  */
88
89 /*
90  * Initialize raw connection block q.
91  */
92 void
93 rip_init()
94 {
95         LIST_INIT(&ripcb);
96         ripcbinfo.listhead = &ripcb;
97         /*
98          * XXX We don't use the hash list for raw IP, but it's easier
99          * to allocate a one entry hash list than it is to check all
100          * over the place for hashbase == NULL.
101          */
102         ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
103         ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask);
104         ripcbinfo.ipi_zone = zinit("ripcb", sizeof(struct inpcb),
105                                    maxsockets, ZONE_INTERRUPT, 0);
106 }
107
108 static struct   sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
109 /*
110  * Setup generic address and protocol structures
111  * for raw_input routine, then pass them along with
112  * mbuf chain.
113  */
114 void
115 rip_input(m, off, proto)
116         struct mbuf *m;
117         int off, proto;
118 {
119         register struct ip *ip = mtod(m, struct ip *);
120         register struct inpcb *inp;
121         struct inpcb *last = 0;
122         struct mbuf *opts = 0;
123
124         ripsrc.sin_addr = ip->ip_src;
125         LIST_FOREACH(inp, &ripcb, inp_list) {
126 #ifdef INET6
127                 if ((inp->inp_vflag & INP_IPV4) == 0)
128                         continue;
129 #endif
130                 if (inp->inp_ip_p && inp->inp_ip_p != proto)
131                         continue;
132                 if (inp->inp_laddr.s_addr &&
133                   inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
134                         continue;
135                 if (inp->inp_faddr.s_addr &&
136                   inp->inp_faddr.s_addr != ip->ip_src.s_addr)
137                         continue;
138                 if (last) {
139                         struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
140
141 #ifdef IPSEC
142                         /* check AH/ESP integrity. */
143                         if (n && ipsec4_in_reject_so(n, last->inp_socket)) {
144                                 m_freem(n);
145                                 ipsecstat.in_polvio++;
146                                 /* do not inject data to pcb */
147                         } else
148 #endif /*IPSEC*/
149                         if (n) {
150                                 if (last->inp_flags & INP_CONTROLOPTS ||
151                                     last->inp_socket->so_options & SO_TIMESTAMP)
152                                     ip_savecontrol(last, &opts, ip, n);
153                                 if (sbappendaddr(&last->inp_socket->so_rcv,
154                                     (struct sockaddr *)&ripsrc, n,
155                                     opts) == 0) {
156                                         /* should notify about lost packet */
157                                         m_freem(n);
158                                         if (opts)
159                                             m_freem(opts);
160                                 } else
161                                         sorwakeup(last->inp_socket);
162                                 opts = 0;
163                         }
164                 }
165                 last = inp;
166         }
167 #ifdef IPSEC
168         /* check AH/ESP integrity. */
169         if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
170                 m_freem(m);
171                 ipsecstat.in_polvio++;
172                 ipstat.ips_delivered--;
173                 /* do not inject data to pcb */
174         } else
175 #endif /*IPSEC*/
176         if (last) {
177                 if (last->inp_flags & INP_CONTROLOPTS ||
178                     last->inp_socket->so_options & SO_TIMESTAMP)
179                         ip_savecontrol(last, &opts, ip, m);
180                 if (sbappendaddr(&last->inp_socket->so_rcv,
181                     (struct sockaddr *)&ripsrc, m, opts) == 0) {
182                         m_freem(m);
183                         if (opts)
184                             m_freem(opts);
185                 } else
186                         sorwakeup(last->inp_socket);
187         } else {
188                 m_freem(m);
189                 ipstat.ips_noproto++;
190                 ipstat.ips_delivered--;
191         }
192 }
193
194 /*
195  * Generate IP header and pass packet to ip_output.
196  * Tack on options user may have setup with control call.
197  */
198 int
199 rip_output(m, so, dst)
200         struct mbuf *m;
201         struct socket *so;
202         u_long dst;
203 {
204         register struct ip *ip;
205         register struct inpcb *inp = sotoinpcb(so);
206         int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
207
208         /*
209          * If the user handed us a complete IP packet, use it.
210          * Otherwise, allocate an mbuf for a header and fill it in.
211          */
212         if ((inp->inp_flags & INP_HDRINCL) == 0) {
213                 if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
214                         m_freem(m);
215                         return(EMSGSIZE);
216                 }
217                 M_PREPEND(m, sizeof(struct ip), M_TRYWAIT);
218                 ip = mtod(m, struct ip *);
219                 ip->ip_tos = inp->inp_ip_tos;
220                 ip->ip_off = 0;
221                 ip->ip_p = inp->inp_ip_p;
222                 ip->ip_len = m->m_pkthdr.len;
223                 ip->ip_src = inp->inp_laddr;
224                 ip->ip_dst.s_addr = dst;
225                 ip->ip_ttl = inp->inp_ip_ttl;
226         } else {
227                 if (m->m_pkthdr.len > IP_MAXPACKET) {
228                         m_freem(m);
229                         return(EMSGSIZE);
230                 }
231                 ip = mtod(m, struct ip *);
232                 /* don't allow both user specified and setsockopt options,
233                    and don't allow packet length sizes that will crash */
234                 if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
235                      && inp->inp_options)
236                     || (ip->ip_len > m->m_pkthdr.len)
237                     || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
238                         m_freem(m);
239                         return EINVAL;
240                 }
241                 if (ip->ip_id == 0)
242 #ifdef RANDOM_IP_ID
243                         ip->ip_id = ip_randomid();
244 #else
245                         ip->ip_id = htons(ip_id++);
246 #endif
247                 /* XXX prevent ip_output from overwriting header fields */
248                 flags |= IP_RAWOUTPUT;
249                 ipstat.ips_rawout++;
250         }
251
252 #ifdef IPSEC
253         if (ipsec_setsocket(m, so) != 0) {
254                 m_freem(m);
255                 return ENOBUFS;
256         }
257 #endif /*IPSEC*/
258
259         return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
260                           inp->inp_moptions));
261 }
262
263 /*
264  * Raw IP socket option processing.
265  */
266 int
267 rip_ctloutput(so, sopt)
268         struct socket *so;
269         struct sockopt *sopt;
270 {
271         struct  inpcb *inp = sotoinpcb(so);
272         int     error, optval;
273
274         if (sopt->sopt_level != IPPROTO_IP)
275                 return (EINVAL);
276
277         error = 0;
278
279         switch (sopt->sopt_dir) {
280         case SOPT_GET:
281                 switch (sopt->sopt_name) {
282                 case IP_HDRINCL:
283                         optval = inp->inp_flags & INP_HDRINCL;
284                         error = sooptcopyout(sopt, &optval, sizeof optval);
285                         break;
286
287                 case IP_FW_ADD:
288                 case IP_FW_GET:
289                         if (ip_fw_ctl_ptr == 0)
290                                 error = ENOPROTOOPT;
291                         else
292                                 error = ip_fw_ctl_ptr(sopt);
293                         break;
294
295 #ifdef DUMMYNET
296                 case IP_DUMMYNET_GET:
297                         if (ip_dn_ctl_ptr == NULL)
298                                 error = ENOPROTOOPT ;
299                         else
300                                 error = ip_dn_ctl_ptr(sopt);
301                         break ;
302 #endif /* DUMMYNET */
303
304                 case MRT_INIT:
305                 case MRT_DONE:
306                 case MRT_ADD_VIF:
307                 case MRT_DEL_VIF:
308                 case MRT_ADD_MFC:
309                 case MRT_DEL_MFC:
310                 case MRT_VERSION:
311                 case MRT_ASSERT:
312                         error = ip_mrouter_get(so, sopt);
313                         break;
314
315                 default:
316                         error = ip_ctloutput(so, sopt);
317                         break;
318                 }
319                 break;
320
321         case SOPT_SET:
322                 switch (sopt->sopt_name) {
323                 case IP_HDRINCL:
324                         error = sooptcopyin(sopt, &optval, sizeof optval,
325                                             sizeof optval);
326                         if (error)
327                                 break;
328                         if (optval)
329                                 inp->inp_flags |= INP_HDRINCL;
330                         else
331                                 inp->inp_flags &= ~INP_HDRINCL;
332                         break;
333
334                 case IP_FW_ADD:
335                 case IP_FW_DEL:
336                 case IP_FW_FLUSH:
337                 case IP_FW_ZERO:
338                 case IP_FW_RESETLOG:
339                         if (ip_fw_ctl_ptr == 0)
340                                 error = ENOPROTOOPT;
341                         else
342                                 error = ip_fw_ctl_ptr(sopt);
343                         break;
344
345 #ifdef DUMMYNET
346                 case IP_DUMMYNET_CONFIGURE:
347                 case IP_DUMMYNET_DEL:
348                 case IP_DUMMYNET_FLUSH:
349                         if (ip_dn_ctl_ptr == NULL)
350                                 error = ENOPROTOOPT ;
351                         else
352                                 error = ip_dn_ctl_ptr(sopt);
353                         break ;
354 #endif
355
356                 case IP_RSVP_ON:
357                         error = ip_rsvp_init(so);
358                         break;
359
360                 case IP_RSVP_OFF:
361                         error = ip_rsvp_done();
362                         break;
363
364                         /* XXX - should be combined */
365                 case IP_RSVP_VIF_ON:
366                         error = ip_rsvp_vif_init(so, sopt);
367                         break;
368                         
369                 case IP_RSVP_VIF_OFF:
370                         error = ip_rsvp_vif_done(so, sopt);
371                         break;
372
373                 case MRT_INIT:
374                 case MRT_DONE:
375                 case MRT_ADD_VIF:
376                 case MRT_DEL_VIF:
377                 case MRT_ADD_MFC:
378                 case MRT_DEL_MFC:
379                 case MRT_VERSION:
380                 case MRT_ASSERT:
381                         error = ip_mrouter_set(so, sopt);
382                         break;
383
384                 default:
385                         error = ip_ctloutput(so, sopt);
386                         break;
387                 }
388                 break;
389         }
390
391         return (error);
392 }
393
394 /*
395  * This function exists solely to receive the PRC_IFDOWN messages which
396  * are sent by if_down().  It looks for an ifaddr whose ifa_addr is sa,
397  * and calls in_ifadown() to remove all routes corresponding to that address.
398  * It also receives the PRC_IFUP messages from if_up() and reinstalls the
399  * interface routes.
400  */
401 void
402 rip_ctlinput(cmd, sa, vip)
403         int cmd;
404         struct sockaddr *sa;
405         void *vip;
406 {
407         struct in_ifaddr *ia;
408         struct ifnet *ifp;
409         int err;
410         int flags;
411
412         switch (cmd) {
413         case PRC_IFDOWN:
414                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
415                         if (ia->ia_ifa.ifa_addr == sa
416                             && (ia->ia_flags & IFA_ROUTE)) {
417                                 /*
418                                  * in_ifscrub kills the interface route.
419                                  */
420                                 in_ifscrub(ia->ia_ifp, ia);
421                                 /*
422                                  * in_ifadown gets rid of all the rest of
423                                  * the routes.  This is not quite the right
424                                  * thing to do, but at least if we are running
425                                  * a routing process they will come back.
426                                  */
427                                 in_ifadown(&ia->ia_ifa, 0);
428                                 break;
429                         }
430                 }
431                 break;
432
433         case PRC_IFUP:
434                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
435                         if (ia->ia_ifa.ifa_addr == sa)
436                                 break;
437                 }
438                 if (ia == 0 || (ia->ia_flags & IFA_ROUTE))
439                         return;
440                 flags = RTF_UP;
441                 ifp = ia->ia_ifa.ifa_ifp;
442
443                 if ((ifp->if_flags & IFF_LOOPBACK)
444                     || (ifp->if_flags & IFF_POINTOPOINT))
445                         flags |= RTF_HOST;
446
447                 err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
448                 if (err == 0)
449                         ia->ia_flags |= IFA_ROUTE;
450                 break;
451         }
452 }
453
454 u_long  rip_sendspace = RIPSNDQ;
455 u_long  rip_recvspace = RIPRCVQ;
456
457 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
458     &rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
459 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
460     &rip_recvspace, 0, "Maximum incoming raw IP datagram size");
461
462 static int
463 rip_attach(struct socket *so, int proto, struct proc *p)
464 {
465         struct inpcb *inp;
466         int error, s;
467
468         inp = sotoinpcb(so);
469         if (inp)
470                 panic("rip_attach");
471         if (p && (error = suser(p)) != 0)
472                 return error;
473
474         error = soreserve(so, rip_sendspace, rip_recvspace);
475         if (error)
476                 return error;
477         s = splnet();
478         error = in_pcballoc(so, &ripcbinfo, p);
479         splx(s);
480         if (error)
481                 return error;
482         inp = (struct inpcb *)so->so_pcb;
483         inp->inp_vflag |= INP_IPV4;
484         inp->inp_ip_p = proto;
485         inp->inp_ip_ttl = ip_defttl;
486 #ifdef IPSEC
487         error = ipsec_init_policy(so, &inp->inp_sp);
488         if (error != 0) {
489                 in_pcbdetach(inp);
490                 return error;
491         }
492 #endif /*IPSEC*/
493         return 0;
494 }
495
496 static int
497 rip_detach(struct socket *so)
498 {
499         struct inpcb *inp;
500
501         inp = sotoinpcb(so);
502         if (inp == 0)
503                 panic("rip_detach");
504         if (so == ip_mrouter)
505                 ip_mrouter_done();
506         ip_rsvp_force_done(so);
507         if (so == ip_rsvpd)
508                 ip_rsvp_done();
509         in_pcbdetach(inp);
510         return 0;
511 }
512
513 static int
514 rip_abort(struct socket *so)
515 {
516         soisdisconnected(so);
517         return rip_detach(so);
518 }
519
520 static int
521 rip_disconnect(struct socket *so)
522 {
523         if ((so->so_state & SS_ISCONNECTED) == 0)
524                 return ENOTCONN;
525         return rip_abort(so);
526 }
527
528 static int
529 rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
530 {
531         struct inpcb *inp = sotoinpcb(so);
532         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
533
534         if (nam->sa_len != sizeof(*addr))
535                 return EINVAL;
536
537         if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) &&
538                                     (addr->sin_family != AF_IMPLINK)) ||
539             (addr->sin_addr.s_addr &&
540              ifa_ifwithaddr((struct sockaddr *)addr) == 0))
541                 return EADDRNOTAVAIL;
542         inp->inp_laddr = addr->sin_addr;
543         return 0;
544 }
545
546 static int
547 rip_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
548 {
549         struct inpcb *inp = sotoinpcb(so);
550         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
551
552         if (nam->sa_len != sizeof(*addr))
553                 return EINVAL;
554         if (TAILQ_EMPTY(&ifnet))
555                 return EADDRNOTAVAIL;
556         if ((addr->sin_family != AF_INET) &&
557             (addr->sin_family != AF_IMPLINK))
558                 return EAFNOSUPPORT;
559         inp->inp_faddr = addr->sin_addr;
560         soisconnected(so);
561         return 0;
562 }
563
564 static int
565 rip_shutdown(struct socket *so)
566 {
567         socantsendmore(so);
568         return 0;
569 }
570
571 static int
572 rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
573          struct mbuf *control, struct proc *p)
574 {
575         struct inpcb *inp = sotoinpcb(so);
576         register u_long dst;
577
578         if (so->so_state & SS_ISCONNECTED) {
579                 if (nam) {
580                         m_freem(m);
581                         return EISCONN;
582                 }
583                 dst = inp->inp_faddr.s_addr;
584         } else {
585                 if (nam == NULL) {
586                         m_freem(m);
587                         return ENOTCONN;
588                 }
589                 dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
590         }
591         return rip_output(m, so, dst);
592 }
593
594 static int
595 rip_pcblist(SYSCTL_HANDLER_ARGS)
596 {
597         int error, i, n, s;
598         struct inpcb *inp, **inp_list;
599         inp_gen_t gencnt;
600         struct xinpgen xig;
601
602         /*
603          * The process of preparing the TCB list is too time-consuming and
604          * resource-intensive to repeat twice on every request.
605          */
606         if (req->oldptr == 0) {
607                 n = ripcbinfo.ipi_count;
608                 req->oldidx = 2 * (sizeof xig)
609                         + (n + n/8) * sizeof(struct xinpcb);
610                 return 0;
611         }
612
613         if (req->newptr != 0)
614                 return EPERM;
615
616         /*
617          * OK, now we're committed to doing something.
618          */
619         s = splnet();
620         gencnt = ripcbinfo.ipi_gencnt;
621         n = ripcbinfo.ipi_count;
622         splx(s);
623
624         xig.xig_len = sizeof xig;
625         xig.xig_count = n;
626         xig.xig_gen = gencnt;
627         xig.xig_sogen = so_gencnt;
628         error = SYSCTL_OUT(req, &xig, sizeof xig);
629         if (error)
630                 return error;
631
632         inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
633         if (inp_list == 0)
634                 return ENOMEM;
635         
636         s = splnet();
637         for (inp = LIST_FIRST(ripcbinfo.listhead), i = 0; inp && i < n;
638              inp = LIST_NEXT(inp, inp_list)) {
639                 if (inp->inp_gencnt <= gencnt)
640                         inp_list[i++] = inp;
641         }
642         splx(s);
643         n = i;
644
645         error = 0;
646         for (i = 0; i < n; i++) {
647                 inp = inp_list[i];
648                 if (inp->inp_gencnt <= gencnt) {
649                         struct xinpcb xi;
650                         xi.xi_len = sizeof xi;
651                         /* XXX should avoid extra copy */
652                         bcopy(inp, &xi.xi_inp, sizeof *inp);
653                         if (inp->inp_socket)
654                                 sotoxsocket(inp->inp_socket, &xi.xi_socket);
655                         error = SYSCTL_OUT(req, &xi, sizeof xi);
656                 }
657         }
658         if (!error) {
659                 /*
660                  * Give the user an updated idea of our state.
661                  * If the generation differs from what we told
662                  * her before, she knows that something happened
663                  * while we were processing this request, and it
664                  * might be necessary to retry.
665                  */
666                 s = splnet();
667                 xig.xig_gen = ripcbinfo.ipi_gencnt;
668                 xig.xig_sogen = so_gencnt;
669                 xig.xig_count = ripcbinfo.ipi_count;
670                 splx(s);
671                 error = SYSCTL_OUT(req, &xig, sizeof xig);
672         }
673         free(inp_list, M_TEMP);
674         return error;
675 }
676
677 SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0,
678             rip_pcblist, "S,xinpcb", "List of active raw IP sockets");
679
680 struct pr_usrreqs rip_usrreqs = {
681         rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect,
682         pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,
683         pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
684         pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,
685         in_setsockaddr, sosend, soreceive, sopoll
686 };