Annotation of 42BSD/sys/netinet/udp_usrreq.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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