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

unix.superglobalmegacorp.com

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