|
|
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: if(udpprintfs) ! 205: printf("udpq: %x.%d %x.%d\n", ui->ui_src, ui->ui_sport, ! 206: ui->ui_dst, ui->ui_dport); ! 207: udpstat.udps_inqfull++; ! 208: bp_free(bp); ! 209: return; ! 210: } ! 211: if ((udp->flags & UDP_CONNECTED) == 0) { ! 212: /* if not acting as a connected protocol, pass user source addr */ ! 213: bp1 = allocb(sizeof(struct udpaddr)); ! 214: if (bp1 == NULL) { ! 215: printf("udpdrint: out of blocks\n"); ! 216: bp_free(bp); ! 217: return; ! 218: } ! 219: bp1->wptr += sizeof(struct udpaddr); ! 220: uap = (struct udpaddr *)bp1->rptr; ! 221: uap->host = ui->ui_src; ! 222: uap->port = ui->ui_sport; ! 223: (*q->next->qinfo->putp)(q->next, bp1); ! 224: } ! 225: while(bp){ ! 226: bp1 = bp->next; ! 227: if (bp1==NULL) ! 228: bp->class |= S_DELIM; ! 229: (*q->next->qinfo->putp)(q->next, bp); ! 230: bp = bp1; ! 231: } ! 232: } ! 233: ! 234: /* ! 235: * first write on this device: ! 236: * data is a command from the user ! 237: */ ! 238: udpduser(bp, udp) ! 239: register struct block *bp; ! 240: register struct udp *udp; ! 241: { ! 242: register struct udpuser *uu; ! 243: ! 244: if ((bp = bp_pullup(bp, sizeof(struct udpuser))) == 0) { ! 245: printf("udpuser short\n"); ! 246: bp_free(bp); ! 247: return; ! 248: } ! 249: uu = (struct udpuser *)bp->rptr; ! 250: switch(uu->cmd){ ! 251: case UDPC_DATAGRAM: ! 252: if (udpbind(udp, uu->sport)) ! 253: goto bad; ! 254: udp->flags &= ~UDP_INIT; ! 255: udpreply(udp); ! 256: break; ! 257: case UDPC_CONNECT: ! 258: if (udpbind(udp, uu->sport)) ! 259: goto bad; ! 260: udp->dport = uu->dport; ! 261: udp->dst = uu->dst; ! 262: udp->flags |= UDP_CONNECTED; ! 263: udp->flags &= ~UDP_INIT; ! 264: udpreply(udp); ! 265: /* pick a local address related to the destination */ ! 266: udp->src = ip_hoston(udp->dst); ! 267: if(udp->src == 0) ! 268: goto bad; ! 269: break; ! 270: case UDPC_LISTEN: ! 271: if (udpbind(udp, uu->sport)) ! 272: goto bad; ! 273: udp->flags |= UDP_LISTEN; ! 274: udp->flags &= ~UDP_INIT; ! 275: break; ! 276: default: ! 277: bad: putctl(udp->rq->next, M_HANGUP); ! 278: return; ! 279: } ! 280: bp_free(bp); ! 281: } ! 282: ! 283: udpreply(udp) ! 284: register struct udp *udp; ! 285: { ! 286: register struct queue *q; ! 287: struct udpreply ur; ! 288: ! 289: ur.reply = UDPR_OK; ! 290: ur.dport = udp->dport; ! 291: ur.dst = udp->dst; ! 292: ur.udpdev = udp - udpconn; ! 293: ! 294: q = udp->rq; ! 295: putcpy(q->next, &ur, sizeof(ur)); ! 296: putctld(q->next, M_DATA); ! 297: } ! 298: ! 299: udpbind(udp, port) ! 300: register struct udp *udp; ! 301: register int port; ! 302: { ! 303: register struct udp *udp2; ! 304: static udp_port udpport = 600; ! 305: ! 306: udp->sport = 0; ! 307: if(port){ ! 308: for(udp2 = &udpconn[0]; udp2 < &udpconn[udpcnt]; udp2++){ ! 309: if(udp2->rq == 0) ! 310: continue; ! 311: if(udp2->sport == port) ! 312: return(1); ! 313: } ! 314: udp->sport = port; ! 315: return(0); ! 316: } ! 317: ! 318: /* pick one for him */ ! 319: if(udpport >= 1024) ! 320: udpport = 600; ! 321: port = udpport; ! 322: while(1){ ! 323: if(udpbind(udp, udpport) == 0){ ! 324: udpport++; ! 325: return(0); ! 326: } ! 327: udpport++; ! 328: if(udpport >= 1024) ! 329: udpport = 600; ! 330: if(udpport == port) /* tried them all */ ! 331: break; ! 332: } ! 333: return(1); ! 334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.