Annotation of XNU/bsd/netinet/raw_ip.c, revision 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.