|
|
1.1 ! root 1: /* ! 2: * udp device driver. ! 3: */ ! 4: ! 5: #include "sys/param.h" ! 6: #include "sys/stream.h" ! 7: #include "sys/conf.h" ! 8: #include "sys/inet/in.h" ! 9: #include "sys/inet/ip.h" ! 10: #include "sys/inet/ip_var.h" ! 11: #include "sys/inet/udp.h" ! 12: #include "sys/inet/udp_var.h" ! 13: #include "sys/inet/udp_user.h" ! 14: ! 15: int udpprintfs; ! 16: long udpdopen(); ! 17: int udpdclose(), udpdput(); ! 18: int udpdosrv(); ! 19: static struct qinit udpdrinit = { noput, NULL, udpdopen, udpdclose, 0, 0 }; ! 20: static struct qinit udpdwinit = { udpdput, udpdosrv, udpdopen, udpdclose, ! 21: UDP_BODY_LIMIT, 64 }; ! 22: struct streamtab udpdinfo = { &udpdrinit, &udpdwinit }; ! 23: ! 24: struct cdevsw udpcdev = cstrinit(&udpdinfo); ! 25: ! 26: extern int udpcnt; /* for netstat */ ! 27: extern struct udp udpconn[]; ! 28: ! 29: in_addr udpbaddst; ! 30: ! 31: long ! 32: udpdopen(q, dev) ! 33: register struct queue *q; ! 34: dev_t dev; ! 35: { ! 36: register struct udp *udp; ! 37: ! 38: dev = minor(dev); ! 39: if(dev >= udpcnt) ! 40: return(0); ! 41: udp = &udpconn[dev]; ! 42: if(q->ptr) ! 43: return(0); ! 44: udp->rq = q; ! 45: udp->flags = UDP_INIT; ! 46: udp->head = udp->tail = NULL; ! 47: q->ptr = (caddr_t)udp; ! 48: q->flag |= QDELIM; ! 49: WR(q)->flag |= QBIGB; ! 50: WR(q)->ptr = (caddr_t)udp; ! 51: return(1); ! 52: } ! 53: ! 54: udpdclose(q) ! 55: register struct queue *q; ! 56: { ! 57: struct udp *udp; ! 58: ! 59: udp = (struct udp *)q->ptr; ! 60: udp->rq = (struct queue *)0; ! 61: q->ptr = (caddr_t)0; ! 62: } ! 63: ! 64: udpdput(q, bp) ! 65: register struct queue *q; ! 66: register struct block *bp; ! 67: { ! 68: ! 69: switch(bp->type){ ! 70: case M_IOCTL: ! 71: bp->type = M_IOCNAK; ! 72: bp->wptr = bp->rptr; ! 73: qreply(q, bp); ! 74: return; ! 75: case M_DATA: ! 76: putq(q, bp); ! 77: if (bp->class&S_DELIM) ! 78: qenable(q); ! 79: return; ! 80: default: ! 81: freeb(bp); ! 82: return; ! 83: } ! 84: } ! 85: ! 86: udpdosrv(q) ! 87: register struct queue *q; ! 88: { ! 89: register struct block *bp; ! 90: register struct udp *udp; ! 91: ! 92: udp = (struct udp *)q->ptr; ! 93: while(bp = getq(q)){ ! 94: if (bp->type != M_DATA) ! 95: panic("udpdosrv"); ! 96: bp->next = NULL; ! 97: if (udp->head == NULL) ! 98: udp->head = bp; ! 99: else ! 100: udp->tail->next = bp; ! 101: udp->tail = bp; ! 102: if ((bp->class & S_DELIM) == 0) ! 103: continue; ! 104: /* ! 105: * have entire datagram ! 106: */ ! 107: bp->class &=~ S_DELIM; ! 108: if (udp->flags & UDP_INIT) ! 109: udpduser(udp->head, udp); ! 110: else { ! 111: if ((udp->flags & UDP_CONNECTED) == 0 ! 112: && udpdaddr(udp) == 0) ! 113: continue; /* couldn't get an addr */ ! 114: udp_output(udp->head, udp); ! 115: } ! 116: udp->head = udp->tail = NULL; ! 117: } ! 118: } ! 119: ! 120: /* ! 121: * extract address from an outbound datagram ! 122: * return 0 if can't find one ! 123: * -- if return 0, have freed bad message and cleared udp->head ! 124: */ ! 125: udpdaddr(udp) ! 126: register struct udp *udp; ! 127: { ! 128: register struct udpaddr *uap; ! 129: ! 130: /* get destination */ ! 131: if((udp->head = bp_pullup(udp->head, sizeof(struct udpaddr))) == NULL) ! 132: return(0); ! 133: uap = (struct udpaddr *)udp->head->rptr; ! 134: udp->dst = uap->host; ! 135: udp->dport = uap->port; ! 136: udp->head->rptr += sizeof(struct udpaddr); ! 137: ! 138: /* host address for datagrams depends on route */ ! 139: if ((udp->flags & UDP_CONNECTED) == 0) { ! 140: udp->src = ip_hoston(udp->dst); ! 141: if(udp->src == 0) { ! 142: udpbaddst = udp->dst; ! 143: bp_free(udp->head); ! 144: udp->head = NULL; ! 145: return(0); ! 146: } ! 147: } ! 148: return(1); ! 149: } ! 150: ! 151: udpdrint(bp, ui) ! 152: register struct block *bp; ! 153: struct udpiphdr *ui; ! 154: { ! 155: register struct block *bp1; ! 156: register struct queue *q; ! 157: register struct udp *udp; ! 158: register struct udpaddr *uap; ! 159: register struct udp *udpend; ! 160: int ps = spl6(); ! 161: ! 162: /* find the udp port */ ! 163: udpend = &udpconn[udpcnt]; ! 164: for (udp = udpconn; udp < udpend; ++udp) { ! 165: if (udp->rq == 0) ! 166: continue; ! 167: if (udp->sport != ui->ui_dport) ! 168: continue; ! 169: if (udp->flags & UDP_LISTEN) ! 170: break; ! 171: if ((udp->flags & UDP_CONNECTED) == 0) ! 172: break; ! 173: if (udp->dport == ui->ui_sport && udp->dst == ui->ui_src) ! 174: break; ! 175: } ! 176: ! 177: if (udp >= udpend) { ! 178: if(udpprintfs) ! 179: printf("no udpconn: %d\n", ui->ui_dport); ! 180: udpstat.udps_badport++; ! 181: bp_free(bp); ! 182: splx(ps); ! 183: return; ! 184: } ! 185: if (udp->flags & UDP_LISTEN) { ! 186: udp->dport = ui->ui_sport; ! 187: udp->dst = ui->ui_src; ! 188: if (udp->src == 0) { ! 189: /* use host name connecting end called us */ ! 190: udp->src = ui->ui_dst; ! 191: } ! 192: udp->flags |= UDP_CONNECTED; ! 193: udp->flags &= ~UDP_LISTEN; ! 194: udpreply(udp); ! 195: } ! 196: splx(ps); ! 197: ! 198: if((q = udp->rq) == NULL) { ! 199: printf("udpdrint but no read queue\n"); ! 200: bp_free(bp); ! 201: return; ! 202: } ! 203: if(q->next->flag & QFULL) { ! 204: udpstat.udps_inqfull++; ! 205: bp_free(bp); ! 206: return; ! 207: } ! 208: if ((udp->flags & UDP_CONNECTED) == 0) { ! 209: /* if not acting as a connected protocol, pass user source addr */ ! 210: bp1 = allocb(sizeof(struct udpaddr)); ! 211: if (bp1 == NULL) { ! 212: printf("udpdrint: out of blocks\n"); ! 213: bp_free(bp); ! 214: return; ! 215: } ! 216: bp1->wptr += sizeof(struct udpaddr); ! 217: uap = (struct udpaddr *)bp1->rptr; ! 218: uap->host = ui->ui_src; ! 219: uap->port = ui->ui_sport; ! 220: (*q->next->qinfo->putp)(q->next, bp1); ! 221: } ! 222: while(bp){ ! 223: bp1 = bp->next; ! 224: if (bp1==NULL) ! 225: bp->class |= S_DELIM; ! 226: (*q->next->qinfo->putp)(q->next, bp); ! 227: bp = bp1; ! 228: } ! 229: } ! 230: ! 231: /* ! 232: * first write on this device: ! 233: * data is a command from the user ! 234: */ ! 235: udpduser(bp, udp) ! 236: register struct block *bp; ! 237: register struct udp *udp; ! 238: { ! 239: register struct udpuser *uu; ! 240: ! 241: if ((bp = bp_pullup(bp, sizeof(struct udpuser))) == 0) { ! 242: printf("udpuser short\n"); ! 243: bp_free(bp); ! 244: return; ! 245: } ! 246: uu = (struct udpuser *)bp->rptr; ! 247: switch(uu->cmd){ ! 248: case UDPC_DATAGRAM: ! 249: if (udpbind(udp, uu->sport)) ! 250: goto bad; ! 251: udp->flags &= ~UDP_INIT; ! 252: udpreply(udp); ! 253: break; ! 254: case UDPC_CONNECT: ! 255: if (udpbind(udp, uu->sport)) ! 256: goto bad; ! 257: udp->dport = uu->dport; ! 258: udp->dst = uu->dst; ! 259: udp->flags |= UDP_CONNECTED; ! 260: udp->flags &= ~UDP_INIT; ! 261: udpreply(udp); ! 262: /* pick a local address related to the destination */ ! 263: udp->src = ip_hoston(udp->dst); ! 264: if(udp->src == 0) ! 265: goto bad; ! 266: break; ! 267: case UDPC_LISTEN: ! 268: if (udpbind(udp, uu->sport)) ! 269: goto bad; ! 270: udp->flags |= UDP_LISTEN; ! 271: udp->flags &= ~UDP_INIT; ! 272: break; ! 273: default: ! 274: bad: putctl(udp->rq->next, M_HANGUP); ! 275: return; ! 276: } ! 277: bp_free(bp); ! 278: } ! 279: ! 280: udpreply(udp) ! 281: register struct udp *udp; ! 282: { ! 283: register struct queue *q; ! 284: struct udpreply ur; ! 285: ! 286: ur.reply = UDPR_OK; ! 287: ur.dport = udp->dport; ! 288: ur.dst = udp->dst; ! 289: ur.udpdev = udp - udpconn; ! 290: ! 291: q = udp->rq; ! 292: putcpy(q->next, &ur, sizeof(ur)); ! 293: putctld(q->next, M_DATA); ! 294: } ! 295: ! 296: udpbind(udp, port) ! 297: register struct udp *udp; ! 298: register int port; ! 299: { ! 300: register struct udp *udp2; ! 301: static udp_port udpport = 600; ! 302: ! 303: udp->sport = 0; ! 304: if(port){ ! 305: for(udp2 = &udpconn[0]; udp2 < &udpconn[udpcnt]; udp2++){ ! 306: if(udp2->rq == 0) ! 307: continue; ! 308: if(udp2->sport == port) ! 309: return(1); ! 310: } ! 311: udp->sport = port; ! 312: return(0); ! 313: } ! 314: ! 315: /* pick one for him */ ! 316: if(udpport >= 1024) ! 317: udpport = 600; ! 318: port = udpport; ! 319: while(1){ ! 320: if(udpbind(udp, udpport) == 0){ ! 321: udpport++; ! 322: return(0); ! 323: } ! 324: udpport++; ! 325: if(udpport >= 1024) ! 326: udpport = 600; ! 327: if(udpport == port) /* tried them all */ ! 328: break; ! 329: } ! 330: return(1); ! 331: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.