Annotation of XNU/bsd/netinet/raw_ip.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.