Annotation of 43BSDTahoe/sys/netinet/udp_usrreq.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that the above copyright notice and this paragraph are
                      7:  * duplicated in all such forms and that any documentation,
                      8:  * advertising materials, and other materials related to such
                      9:  * distribution and use acknowledge that the software was developed
                     10:  * by the University of California, Berkeley.  The name of the
                     11:  * University may not be used to endorse or promote products derived
                     12:  * from this software without specific prior written permission.
                     13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     16:  *
                     17:  *     @(#)udp_usrreq.c        7.7 (Berkeley) 6/29/88
                     18:  */
                     19: 
                     20: #include "param.h"
                     21: #include "dir.h"
                     22: #include "user.h"
                     23: #include "mbuf.h"
                     24: #include "protosw.h"
                     25: #include "socket.h"
                     26: #include "socketvar.h"
                     27: #include "errno.h"
                     28: #include "stat.h"
                     29: 
                     30: #include "../net/if.h"
                     31: #include "../net/route.h"
                     32: 
                     33: #include "in.h"
                     34: #include "in_pcb.h"
                     35: #include "in_systm.h"
                     36: #include "ip.h"
                     37: #include "ip_var.h"
                     38: #include "ip_icmp.h"
                     39: #include "udp.h"
                     40: #include "udp_var.h"
                     41: 
                     42: /*
                     43:  * UDP protocol implementation.
                     44:  * Per RFC 768, August, 1980.
                     45:  */
                     46: udp_init()
                     47: {
                     48: 
                     49:        udb.inp_next = udb.inp_prev = &udb;
                     50: }
                     51: 
                     52: #ifndef        COMPAT_42
                     53: int    udpcksum = 1;
                     54: #else
                     55: int    udpcksum = 0;           /* XXX */
                     56: #endif
                     57: int    udp_ttl = UDP_TTL;
                     58: 
                     59: struct sockaddr_in udp_in = { AF_INET };
                     60: 
                     61: udp_input(m0, ifp)
                     62:        struct mbuf *m0;
                     63:        struct ifnet *ifp;
                     64: {
                     65:        register struct udpiphdr *ui;
                     66:        register struct inpcb *inp;
                     67:        register struct mbuf *m;
                     68:        int len;
                     69:        struct ip ip;
                     70: 
                     71:        /*
                     72:         * Get IP and UDP header together in first mbuf.
                     73:         */
                     74:        m = m0;
                     75:        if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) &&
                     76:            (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
                     77:                udpstat.udps_hdrops++;
                     78:                return;
                     79:        }
                     80:        ui = mtod(m, struct udpiphdr *);
                     81:        if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
                     82:                ip_stripoptions((struct ip *)ui, (struct mbuf *)0);
                     83: 
                     84:        /*
                     85:         * Make mbuf data length reflect UDP length.
                     86:         * If not enough data to reflect UDP length, drop.
                     87:         */
                     88:        len = ntohs((u_short)ui->ui_ulen);
                     89:        if (((struct ip *)ui)->ip_len != len) {
                     90:                if (len > ((struct ip *)ui)->ip_len) {
                     91:                        udpstat.udps_badlen++;
                     92:                        goto bad;
                     93:                }
                     94:                m_adj(m, len - ((struct ip *)ui)->ip_len);
                     95:                /* ((struct ip *)ui)->ip_len = len; */
                     96:        }
                     97:        /*
                     98:         * Save a copy of the IP header in case we want restore it for ICMP.
                     99:         */
                    100:        ip = *(struct ip*)ui;
                    101: 
                    102:        /*
                    103:         * Checksum extended UDP header and data.
                    104:         */
                    105:        if (udpcksum && ui->ui_sum) {
                    106:                ui->ui_next = ui->ui_prev = 0;
                    107:                ui->ui_x1 = 0;
                    108:                ui->ui_len = ui->ui_ulen;
                    109:                if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) {
                    110:                        udpstat.udps_badsum++;
                    111:                        m_freem(m);
                    112:                        return;
                    113:                }
                    114:        }
                    115: 
                    116:        /*
                    117:         * Locate pcb for datagram.
                    118:         */
                    119:        inp = in_pcblookup(&udb,
                    120:            ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
                    121:                INPLOOKUP_WILDCARD);
                    122:        if (inp == 0) {
                    123:                /* don't send ICMP response for broadcast packet */
                    124:                if (in_broadcast(ui->ui_dst))
                    125:                        goto bad;
                    126:                *(struct ip *)ui = ip;
                    127:                icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT,
                    128:                    ifp);
                    129:                return;
                    130:        }
                    131: 
                    132:        /*
                    133:         * Construct sockaddr format source address.
                    134:         * Stuff source address and datagram in user buffer.
                    135:         */
                    136:        udp_in.sin_port = ui->ui_sport;
                    137:        udp_in.sin_addr = ui->ui_src;
                    138:        m->m_len -= sizeof (struct udpiphdr);
                    139:        m->m_off += sizeof (struct udpiphdr);
                    140:        if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
                    141:            m, (struct mbuf *)0) == 0)
                    142:                goto bad;
                    143:        sorwakeup(inp->inp_socket);
                    144:        return;
                    145: bad:
                    146:        m_freem(m);
                    147: }
                    148: 
                    149: /*
                    150:  * Notify a udp user of an asynchronous error;
                    151:  * just wake up so that he can collect error status.
                    152:  */
                    153: udp_notify(inp)
                    154:        register struct inpcb *inp;
                    155: {
                    156: 
                    157:        sorwakeup(inp->inp_socket);
                    158:        sowwakeup(inp->inp_socket);
                    159: }
                    160: 
                    161: udp_ctlinput(cmd, sa)
                    162:        int cmd;
                    163:        struct sockaddr *sa;
                    164: {
                    165:        extern u_char inetctlerrmap[];
                    166:        struct sockaddr_in *sin;
                    167:        int in_rtchange();
                    168: 
                    169:        if ((unsigned)cmd > PRC_NCMDS)
                    170:                return;
                    171:        if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
                    172:                return;
                    173:        sin = (struct sockaddr_in *)sa;
                    174:        if (sin->sin_addr.s_addr == INADDR_ANY)
                    175:                return;
                    176: 
                    177:        switch (cmd) {
                    178: 
                    179:        case PRC_QUENCH:
                    180:                break;
                    181: 
                    182:        case PRC_ROUTEDEAD:
                    183:        case PRC_REDIRECT_NET:
                    184:        case PRC_REDIRECT_HOST:
                    185:        case PRC_REDIRECT_TOSNET:
                    186:        case PRC_REDIRECT_TOSHOST:
                    187:                in_pcbnotify(&udb, &sin->sin_addr, 0, in_rtchange);
                    188:                break;
                    189: 
                    190:        default:
                    191:                if (inetctlerrmap[cmd] == 0)
                    192:                        return;         /* XXX */
                    193:                in_pcbnotify(&udb, &sin->sin_addr, (int)inetctlerrmap[cmd],
                    194:                        udp_notify);
                    195:        }
                    196: }
                    197: 
                    198: udp_output(inp, m0)
                    199:        register struct inpcb *inp;
                    200:        struct mbuf *m0;
                    201: {
                    202:        register struct mbuf *m;
                    203:        register struct udpiphdr *ui;
                    204:        register int len = 0;
                    205: 
                    206:        /*
                    207:         * Calculate data length and get a mbuf
                    208:         * for UDP and IP headers.
                    209:         */
                    210:        for (m = m0; m; m = m->m_next)
                    211:                len += m->m_len;
                    212:        MGET(m, M_DONTWAIT, MT_HEADER);
                    213:        if (m == 0) {
                    214:                m_freem(m0);
                    215:                return (ENOBUFS);
                    216:        }
                    217: 
                    218:        /*
                    219:         * Fill in mbuf with extended UDP header
                    220:         * and addresses and length put into network format.
                    221:         */
                    222:        m->m_off = MMAXOFF - sizeof (struct udpiphdr);
                    223:        m->m_len = sizeof (struct udpiphdr);
                    224:        m->m_next = m0;
                    225:        ui = mtod(m, struct udpiphdr *);
                    226:        ui->ui_next = ui->ui_prev = 0;
                    227:        ui->ui_x1 = 0;
                    228:        ui->ui_pr = IPPROTO_UDP;
                    229:        ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
                    230:        ui->ui_src = inp->inp_laddr;
                    231:        ui->ui_dst = inp->inp_faddr;
                    232:        ui->ui_sport = inp->inp_lport;
                    233:        ui->ui_dport = inp->inp_fport;
                    234:        ui->ui_ulen = ui->ui_len;
                    235: 
                    236:        /*
                    237:         * Stuff checksum and output datagram.
                    238:         */
                    239:        ui->ui_sum = 0;
                    240:        if (udpcksum) {
                    241:            if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
                    242:                ui->ui_sum = 0xffff;
                    243:        }
                    244:        ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
                    245:        ((struct ip *)ui)->ip_ttl = udp_ttl;
                    246:        return (ip_output(m, inp->inp_options, &inp->inp_route,
                    247:            inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)));
                    248: }
                    249: 
                    250: u_long udp_sendspace = 2048;           /* really max datagram size */
                    251: u_long udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */
                    252: 
                    253: /*ARGSUSED*/
                    254: udp_usrreq(so, req, m, nam, rights)
                    255:        struct socket *so;
                    256:        int req;
                    257:        struct mbuf *m, *nam, *rights;
                    258: {
                    259:        struct inpcb *inp = sotoinpcb(so);
                    260:        int error = 0;
                    261: 
                    262:        if (req == PRU_CONTROL)
                    263:                return (in_control(so, (int)m, (caddr_t)nam,
                    264:                        (struct ifnet *)rights));
                    265:        if (rights && rights->m_len) {
                    266:                error = EINVAL;
                    267:                goto release;
                    268:        }
                    269:        if (inp == NULL && req != PRU_ATTACH) {
                    270:                error = EINVAL;
                    271:                goto release;
                    272:        }
                    273:        switch (req) {
                    274: 
                    275:        case PRU_ATTACH:
                    276:                if (inp != NULL) {
                    277:                        error = EINVAL;
                    278:                        break;
                    279:                }
                    280:                error = in_pcballoc(so, &udb);
                    281:                if (error)
                    282:                        break;
                    283:                error = soreserve(so, udp_sendspace, udp_recvspace);
                    284:                if (error)
                    285:                        break;
                    286:                break;
                    287: 
                    288:        case PRU_DETACH:
                    289:                in_pcbdetach(inp);
                    290:                break;
                    291: 
                    292:        case PRU_BIND:
                    293:                error = in_pcbbind(inp, nam);
                    294:                break;
                    295: 
                    296:        case PRU_LISTEN:
                    297:                error = EOPNOTSUPP;
                    298:                break;
                    299: 
                    300:        case PRU_CONNECT:
                    301:                if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    302:                        error = EISCONN;
                    303:                        break;
                    304:                }
                    305:                error = in_pcbconnect(inp, nam);
                    306:                if (error == 0)
                    307:                        soisconnected(so);
                    308:                break;
                    309: 
                    310:        case PRU_CONNECT2:
                    311:                error = EOPNOTSUPP;
                    312:                break;
                    313: 
                    314:        case PRU_ACCEPT:
                    315:                error = EOPNOTSUPP;
                    316:                break;
                    317: 
                    318:        case PRU_DISCONNECT:
                    319:                if (inp->inp_faddr.s_addr == INADDR_ANY) {
                    320:                        error = ENOTCONN;
                    321:                        break;
                    322:                }
                    323:                in_pcbdisconnect(inp);
                    324:                so->so_state &= ~SS_ISCONNECTED;                /* XXX */
                    325:                break;
                    326: 
                    327:        case PRU_SHUTDOWN:
                    328:                socantsendmore(so);
                    329:                break;
                    330: 
                    331:        case PRU_SEND: {
                    332:                struct in_addr laddr;
                    333:                int s;
                    334: 
                    335:                if (nam) {
                    336:                        laddr = inp->inp_laddr;
                    337:                        if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    338:                                error = EISCONN;
                    339:                                break;
                    340:                        }
                    341:                        /*
                    342:                         * Must block input while temporarily connected.
                    343:                         */
                    344:                        s = splnet();
                    345:                        error = in_pcbconnect(inp, nam);
                    346:                        if (error) {
                    347:                                splx(s);
                    348:                                break;
                    349:                        }
                    350:                } else {
                    351:                        if (inp->inp_faddr.s_addr == INADDR_ANY) {
                    352:                                error = ENOTCONN;
                    353:                                break;
                    354:                        }
                    355:                }
                    356:                error = udp_output(inp, m);
                    357:                m = NULL;
                    358:                if (nam) {
                    359:                        in_pcbdisconnect(inp);
                    360:                        inp->inp_laddr = laddr;
                    361:                        splx(s);
                    362:                }
                    363:                }
                    364:                break;
                    365: 
                    366:        case PRU_ABORT:
                    367:                soisdisconnected(so);
                    368:                in_pcbdetach(inp);
                    369:                break;
                    370: 
                    371:        case PRU_SOCKADDR:
                    372:                in_setsockaddr(inp, nam);
                    373:                break;
                    374: 
                    375:        case PRU_PEERADDR:
                    376:                in_setpeeraddr(inp, nam);
                    377:                break;
                    378: 
                    379:        case PRU_SENSE:
                    380:                /*
                    381:                 * stat: don't bother with a blocksize.
                    382:                 */
                    383:                return (0);
                    384: 
                    385:        case PRU_SENDOOB:
                    386:        case PRU_FASTTIMO:
                    387:        case PRU_SLOWTIMO:
                    388:        case PRU_PROTORCV:
                    389:        case PRU_PROTOSEND:
                    390:                error =  EOPNOTSUPP;
                    391:                break;
                    392: 
                    393:        case PRU_RCVD:
                    394:        case PRU_RCVOOB:
                    395:                return (EOPNOTSUPP);    /* do not free mbuf's */
                    396: 
                    397:        default:
                    398:                panic("udp_usrreq");
                    399:        }
                    400: release:
                    401:        if (m != NULL)
                    402:                m_freem(m);
                    403:        return (error);
                    404: }

unix.superglobalmegacorp.com

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