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

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

unix.superglobalmegacorp.com

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