Annotation of 42BSD/sys/netinet/udp_usrreq.c, revision 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.