Annotation of cci/sys/netinet/in_pcb.c, revision 1.1.1.1

1.1       root        1: /*     in_pcb.c        6.1     83/07/29        */
                      2: 
                      3: #include "../h/param.h"
                      4: #include "../h/systm.h"
                      5: #include "../h/dir.h"
                      6: #include "../h/user.h"
                      7: #include "../h/mbuf.h"
                      8: #include "../h/socket.h"
                      9: #include "../h/socketvar.h"
                     10: #include "../netinet/in.h"
                     11: #include "../netinet/in_systm.h"
                     12: #include "../net/if.h"
                     13: #include "../net/route.h"
                     14: #include "../netinet/in_pcb.h"
                     15: #include "../h/protosw.h"
                     16: 
                     17: struct in_addr zeroin_addr;
                     18: 
                     19: in_pcballoc(so, head)
                     20:        struct socket *so;
                     21:        struct inpcb *head;
                     22: {
                     23:        struct mbuf *m;
                     24:        register struct inpcb *inp;
                     25: 
                     26:        m = m_getclr(M_DONTWAIT, MT_PCB);
                     27:        MBUFNULL(45, m);        /* for debugging */
                     28:        if (m == NULL)
                     29:                return (ENOBUFS);
                     30:        inp = mtod(m, struct inpcb *);
                     31:        inp->inp_head = head;
                     32:        inp->inp_socket = so;
                     33:        insque(inp, head);
                     34:        so->so_pcb = (caddr_t)inp;
                     35:        return (0);
                     36: }
                     37:        
                     38: in_pcbbind(inp, nam)
                     39:        register struct inpcb *inp;
                     40:        struct mbuf *nam;
                     41: {
                     42:        register struct socket *so = inp->inp_socket;
                     43:        register struct inpcb *head = inp->inp_head;
                     44:        register struct sockaddr_in *sin;
                     45:        u_short lport = 0;
                     46: 
                     47:        if (ifnet == 0)
                     48:                return (EADDRNOTAVAIL);
                     49:        if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
                     50:                return (EINVAL);
                     51:        if (nam == 0)
                     52:                goto noname;
                     53:        sin = mtod(nam, struct sockaddr_in *);
                     54:        if (nam->m_len != sizeof (*sin))
                     55:                return (EINVAL);
                     56:        if (sin->sin_addr.s_addr != INADDR_ANY) {
                     57:                int tport = sin->sin_port;
                     58: 
                     59:                sin->sin_port = 0;              /* yech... */
                     60:                if (if_ifwithaddr((struct sockaddr *)sin) == 0)
                     61:                        return (EADDRNOTAVAIL);
                     62:                sin->sin_port = tport;
                     63:        }
                     64:        lport = sin->sin_port;
                     65:        if (lport) {
                     66:                u_short aport = ntohs(lport);
                     67:                int wild = 0;
                     68: 
                     69:                /* GROSS */
                     70:                if (aport < IPPORT_RESERVED && u.u_uid != 0)
                     71:                        return (EACCES);
                     72:                /* even GROSSER, but this is the Internet */
                     73:                if ((so->so_options & SO_REUSEADDR) == 0 &&
                     74:                    ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
                     75:                     (so->so_options & SO_ACCEPTCONN) == 0))
                     76:                        wild = INPLOOKUP_WILDCARD;
                     77:                if (in_pcblookup(head,
                     78:                    zeroin_addr, 0, sin->sin_addr, lport, wild))
                     79:                        return (EADDRINUSE);
                     80:        }
                     81:        inp->inp_laddr = sin->sin_addr;
                     82: noname:
                     83:        if (lport == 0)
                     84:                do {
                     85:                        if (head->inp_lport++ < IPPORT_RESERVED)
                     86:                                head->inp_lport = IPPORT_RESERVED;
                     87:                        lport = htons(head->inp_lport);
                     88:                } while (in_pcblookup(head,
                     89:                            zeroin_addr, 0, inp->inp_laddr, lport, 0));
                     90:        inp->inp_lport = lport;
                     91:        return (0);
                     92: }
                     93: 
                     94: /*
                     95:  * Connect from a socket to a specified address.
                     96:  * Both address and port must be specified in argument sin.
                     97:  * If don't have a local address for this socket yet,
                     98:  * then pick one.
                     99:  */
                    100: in_pcbconnect(inp, nam)
                    101:        struct inpcb *inp;
                    102:        struct mbuf *nam;
                    103: {
                    104:        struct ifnet *ifp;
                    105:        struct sockaddr_in *ifaddr;
                    106:        register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
                    107: 
                    108:        if (nam->m_len != sizeof (*sin))
                    109:                return (EINVAL);
                    110:        if (sin->sin_family != AF_INET)
                    111:                return (EAFNOSUPPORT);
                    112:        if (sin->sin_addr.s_addr == INADDR_ANY || sin->sin_port == 0)
                    113:                return (EADDRNOTAVAIL);
                    114:        if (inp->inp_laddr.s_addr == INADDR_ANY) {
                    115:                ifp = if_ifonnetof(in_netof(sin->sin_addr));
                    116:                if (ifp == 0) {
                    117:                        /*
                    118:                         * We should select the interface based on
                    119:                         * the route to be used, but for udp this would
                    120:                         * result in two calls to rtalloc for each packet
                    121:                         * sent; hardly worthwhile...
                    122:                         */
                    123:                        ifp = if_ifwithaf(AF_INET);
                    124:                        if (ifp == 0)
                    125:                                return (EADDRNOTAVAIL);
                    126:                }
                    127:                ifaddr = (struct sockaddr_in *)&ifp->if_addr;
                    128:        }
                    129:        if (in_pcblookup(inp->inp_head,
                    130:            sin->sin_addr,
                    131:            sin->sin_port,
                    132:            inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
                    133:            inp->inp_lport,
                    134:            0))
                    135:                return (EADDRINUSE);
                    136:        if (inp->inp_laddr.s_addr == INADDR_ANY) {
                    137:                if (inp->inp_lport == 0)
                    138:                        in_pcbbind(inp, (struct mbuf *)0);
                    139:                inp->inp_laddr = ifaddr->sin_addr;
                    140:        }
                    141:        inp->inp_faddr = sin->sin_addr;
                    142:        inp->inp_fport = sin->sin_port;
                    143:        return (0);
                    144: }
                    145: 
                    146: in_pcbdisconnect(inp)
                    147:        struct inpcb *inp;
                    148: {
                    149: 
                    150:        inp->inp_faddr.s_addr = INADDR_ANY;
                    151:        inp->inp_fport = 0;
                    152:        if (inp->inp_socket->so_state & SS_NOFDREF)
                    153:                in_pcbdetach(inp);
                    154: }
                    155: 
                    156: in_pcbdetach(inp)
                    157:        struct inpcb *inp;
                    158: {
                    159:        struct socket *so = inp->inp_socket;
                    160: 
                    161:        so->so_pcb = 0;
                    162:        sofree(so);
                    163:        if (inp->inp_route.ro_rt)
                    164:                rtfree(inp->inp_route.ro_rt);
                    165:        remque(inp);
                    166:        (void) m_free(dtom(inp));
                    167: }
                    168: 
                    169: in_setsockaddr(inp, nam)
                    170:        register struct inpcb *inp;
                    171:        struct mbuf *nam;
                    172: {
                    173:        register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
                    174:        
                    175:        nam->m_len = sizeof (*sin);
                    176:        sin = mtod(nam, struct sockaddr_in *);
                    177:        bzero((caddr_t)sin, sizeof (*sin));
                    178:        sin->sin_family = AF_INET;
                    179:        sin->sin_port = inp->inp_lport;
                    180:        sin->sin_addr = inp->inp_laddr;
                    181: }
                    182: 
                    183: in_setpeeraddr(inp, nam)
                    184:        register struct inpcb *inp;
                    185:        struct mbuf *nam;
                    186: {
                    187:        register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
                    188:        
                    189:        nam->m_len = sizeof (*sin);
                    190:        sin = mtod(nam, struct sockaddr_in *);
                    191:        bzero((caddr_t)sin, sizeof (*sin));
                    192:        sin->sin_family = AF_INET;
                    193:        sin->sin_port = inp->inp_fport;
                    194:        sin->sin_addr = inp->inp_faddr;
                    195: }
                    196: 
                    197: /*
                    198:  * Pass an error to all internet connections
                    199:  * associated with address sin.  Call the
                    200:  * protocol specific routine to clean up the
                    201:  * mess afterwards.
                    202:  */
                    203: in_pcbnotify(head, dst, errno, abort)
                    204:        struct inpcb *head;
                    205:        register struct in_addr *dst;
                    206:        int errno, (*abort)();
                    207: {
                    208:        register struct inpcb *inp, *oinp;
                    209:        int s = splimp();
                    210: 
                    211:        for (inp = head->inp_next; inp != head;) {
                    212:                if (inp->inp_faddr.s_addr != dst->s_addr) {
                    213:        next:
                    214:                        inp = inp->inp_next;
                    215:                        continue;
                    216:                }
                    217:                if (inp->inp_socket == 0)
                    218:                        goto next;
                    219:                inp->inp_socket->so_error = errno;
                    220:                oinp = inp;
                    221:                inp = inp->inp_next;
                    222:                (*abort)(oinp);
                    223:        }
                    224:        splx(s);
                    225: }
                    226: 
                    227: struct inpcb *
                    228: in_pcblookup(head, faddr, fport, laddr, lport, flags)
                    229:        struct inpcb *head;
                    230:        struct in_addr faddr, laddr;
                    231:        u_short fport, lport;
                    232:        int flags;
                    233: {
                    234:        register struct inpcb *inp, *match = 0;
                    235:        int matchwild = 3, wildcard;
                    236: 
                    237:        for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
                    238:                if (inp->inp_lport != lport)
                    239:                        continue;
                    240:                wildcard = 0;
                    241:                if (inp->inp_laddr.s_addr != INADDR_ANY) {
                    242:                        if (laddr.s_addr == INADDR_ANY)
                    243:                                wildcard++;
                    244:                        else if (inp->inp_laddr.s_addr != laddr.s_addr)
                    245:                                continue;
                    246:                } else {
                    247:                        if (laddr.s_addr != INADDR_ANY)
                    248:                                wildcard++;
                    249:                }
                    250:                if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    251:                        if (faddr.s_addr == INADDR_ANY)
                    252:                                wildcard++;
                    253:                        else if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    254:                            inp->inp_fport != fport)
                    255:                                continue;
                    256:                } else {
                    257:                        if (faddr.s_addr != INADDR_ANY)
                    258:                                wildcard++;
                    259:                }
                    260:                if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
                    261:                        continue;
                    262:                if (wildcard < matchwild) {
                    263:                        match = inp;
                    264:                        matchwild = wildcard;
                    265:                        if (matchwild == 0)
                    266:                                break;
                    267:                }
                    268:        }
                    269:        return (match);
                    270: }

unix.superglobalmegacorp.com

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