00001 #include "packet_solaris_dlpi.h"
00002
00003
00004
00005
00006 #ifdef _SOLARIS_
00007
00008 #include "packet.h"
00009 #include <stdio.h>
00010 #include <sys/dlpi.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <strings.h>
00014 #include <stdlib.h>
00015 #include <sys/types.h>
00016 #include <sys/stat.h>
00017 #include <fcntl.h>
00018 #include <errno.h>
00019 #include <stropts.h>
00020 #include <sys/systeminfo.h>
00021 #include <ctype.h>
00022 #include <memory.h>
00023 #include <sys/bufmod.h>
00024
00025 #define DEBUG
00026
00027 #define MAXDLBUF 8192
00028 #define PCAP_DEV_PREFIX "/dev"
00029 typedef unsigned int u_int32;
00030
00031 static u_int32 ctlbuf[MAXDLBUF];
00032 static struct strbuf ctl = {
00033 MAXDLBUF,
00034 0,
00035 (char *)ctlbuf
00036 };
00037
00038
00039 extern GlobalVars Globals;
00040
00041
00042
00043
00044 static int send_request(int fd, char *ptr, int len, char *what){
00045 struct strbuf ctl;
00046 int flags;
00047
00048 ctl.maxlen = 0;
00049 ctl.len = len;
00050 ctl.buf = ptr;
00051
00052 flags = 0;
00053 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
00054 printf("send_request: putmsg \"%s\": %s", what, strerror(errno));
00055 return (-1);
00056 }
00057 return (0);
00058 }
00059
00060
00061
00062
00063
00064 static int dlinforeq(int fd){
00065 dl_info_req_t req;
00066
00067 req.dl_primitive = DL_INFO_REQ;
00068
00069 return (send_request(fd, (char *)&req, sizeof(req), "info"));
00070 }
00071
00072
00073
00074
00075
00076 static char* dlstrerror(u_int32 dl_errno){
00077 static char errstring[6+2+8+1];
00078
00079 switch (dl_errno) {
00080
00081 case DL_ACCESS:
00082 return ("Improper permissions for request");
00083
00084 case DL_BADADDR:
00085 return ("DLSAP addr in improper format or invalid");
00086
00087 case DL_BADCORR:
00088 return ("Seq number not from outstand DL_CONN_IND");
00089
00090 case DL_BADDATA:
00091 return ("User data exceeded provider limit");
00092
00093 case DL_BADPPA:
00094
00095
00096
00097
00098 return ("Specified PPA (device unit) was invalid");
00099
00100 case DL_BADPRIM:
00101 return ("Primitive received not known by provider");
00102
00103 case DL_BADQOSPARAM:
00104 return ("QOS parameters contained invalid values");
00105
00106 case DL_BADQOSTYPE:
00107 return ("QOS structure type is unknown/unsupported");
00108
00109 case DL_BADSAP:
00110 return ("Bad LSAP selector");
00111
00112 case DL_BADTOKEN:
00113 return ("Token used not an active stream");
00114
00115 case DL_BOUND:
00116 return ("Attempted second bind with dl_max_conind");
00117
00118 case DL_INITFAILED:
00119 return ("Physical link initialization failed");
00120
00121 case DL_NOADDR:
00122 return ("Provider couldn't allocate alternate address");
00123
00124 case DL_NOTINIT:
00125 return ("Physical link not initialized");
00126
00127 case DL_OUTSTATE:
00128 return ("Primitive issued in improper state");
00129
00130 case DL_SYSERR:
00131 return ("UNIX system error occurred");
00132
00133 case DL_UNSUPPORTED:
00134 return ("Requested service not supplied by provider");
00135
00136 case DL_UNDELIVERABLE:
00137 return ("Previous data unit could not be delivered");
00138
00139 case DL_NOTSUPPORTED:
00140 return ("Primitive is known but not supported");
00141
00142 case DL_TOOMANY:
00143 return ("Limit exceeded");
00144
00145 case DL_NOTENAB:
00146 return ("Promiscuous mode not enabled");
00147
00148 case DL_BUSY:
00149 return ("Other streams for PPA in post-attached");
00150
00151 case DL_NOAUTO:
00152 return ("Automatic handling XID&TEST not supported");
00153
00154 case DL_NOXIDAUTO:
00155 return ("Automatic handling of XID not supported");
00156
00157 case DL_NOTESTAUTO:
00158 return ("Automatic handling of TEST not supported");
00159
00160 case DL_XIDAUTO:
00161 return ("Automatic handling of XID response");
00162
00163 case DL_TESTAUTO:
00164 return ("Automatic handling of TEST response");
00165
00166 case DL_PENDING:
00167 return ("Pending outstanding connect indications");
00168
00169 default:
00170 sprintf(errstring, "Error %02x", dl_errno);
00171 return (errstring);
00172 }
00173 }
00174
00175
00176
00177
00178 static char* dlprim(u_int32 prim){
00179 static char primbuf[80];
00180
00181 switch (prim) {
00182
00183 case DL_INFO_REQ:
00184 return ("DL_INFO_REQ");
00185
00186 case DL_INFO_ACK:
00187 return ("DL_INFO_ACK");
00188
00189 case DL_ATTACH_REQ:
00190 return ("DL_ATTACH_REQ");
00191
00192 case DL_DETACH_REQ:
00193 return ("DL_DETACH_REQ");
00194
00195 case DL_BIND_REQ:
00196 return ("DL_BIND_REQ");
00197
00198 case DL_BIND_ACK:
00199 return ("DL_BIND_ACK");
00200
00201 case DL_UNBIND_REQ:
00202 return ("DL_UNBIND_REQ");
00203
00204 case DL_OK_ACK:
00205 return ("DL_OK_ACK");
00206
00207 case DL_ERROR_ACK:
00208 return ("DL_ERROR_ACK");
00209
00210 case DL_SUBS_BIND_REQ:
00211 return ("DL_SUBS_BIND_REQ");
00212
00213 case DL_SUBS_BIND_ACK:
00214 return ("DL_SUBS_BIND_ACK");
00215
00216 case DL_UNITDATA_REQ:
00217 return ("DL_UNITDATA_REQ");
00218
00219 case DL_UNITDATA_IND:
00220 return ("DL_UNITDATA_IND");
00221
00222 case DL_UDERROR_IND:
00223 return ("DL_UDERROR_IND");
00224
00225 case DL_UDQOS_REQ:
00226 return ("DL_UDQOS_REQ");
00227
00228 case DL_CONNECT_REQ:
00229 return ("DL_CONNECT_REQ");
00230
00231 case DL_CONNECT_IND:
00232 return ("DL_CONNECT_IND");
00233
00234 case DL_CONNECT_RES:
00235 return ("DL_CONNECT_RES");
00236
00237 case DL_CONNECT_CON:
00238 return ("DL_CONNECT_CON");
00239
00240 case DL_TOKEN_REQ:
00241 return ("DL_TOKEN_REQ");
00242
00243 case DL_TOKEN_ACK:
00244 return ("DL_TOKEN_ACK");
00245
00246 case DL_DISCONNECT_REQ:
00247 return ("DL_DISCONNECT_REQ");
00248
00249 case DL_DISCONNECT_IND:
00250 return ("DL_DISCONNECT_IND");
00251
00252 case DL_RESET_REQ:
00253 return ("DL_RESET_REQ");
00254
00255 case DL_RESET_IND:
00256 return ("DL_RESET_IND");
00257
00258 case DL_RESET_RES:
00259 return ("DL_RESET_RES");
00260
00261 case DL_RESET_CON:
00262 return ("DL_RESET_CON");
00263
00264 default:
00265 (void) sprintf(primbuf, "unknown primitive 0x%x", prim);
00266 return (primbuf);
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275 static int recv_ack(int fd, int size, const char *what, char *bufp){
00276 union DL_primitives *dlp;
00277 struct strbuf ctl;
00278 int flags;
00279
00280 ctl.maxlen = MAXDLBUF;
00281 ctl.len = 0;
00282 ctl.buf = bufp;
00283
00284 flags = 0;
00285 if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
00286 printf("recv_ack: %s getmsg: %s", what, strerror(errno));
00287 return (-1);
00288 }
00289
00290 dlp = (union DL_primitives *) ctl.buf;
00291 switch (dlp->dl_primitive) {
00292
00293 case DL_INFO_ACK:
00294 case DL_BIND_ACK:
00295 case DL_OK_ACK:
00296 #ifdef DL_HP_PPA_ACK
00297 case DL_HP_PPA_ACK:
00298 #endif
00299
00300 break;
00301
00302 case DL_ERROR_ACK:
00303 switch (dlp->error_ack.dl_errno) {
00304
00305 case DL_SYSERR:
00306 printf("recv_ack: %s: UNIX error - %s", what, strerror(dlp->error_ack.dl_unix_errno));
00307 break;
00308
00309 default:
00310 printf("recv_ack: %s: %s", what, dlstrerror(dlp->error_ack.dl_errno));
00311 break;
00312 }
00313 return (-1);
00314
00315 default:
00316 printf("recv_ack: %s: Unexpected primitive ack %s", what, dlprim(dlp->dl_primitive));
00317 return (-1);
00318 }
00319
00320 if (ctl.len < size) {
00321 printf("recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size);
00322 return (-1);
00323 }
00324 return (ctl.len);
00325 }
00326
00327
00328
00329
00330
00331 static int dlinfoack(int fd, char *bufp){
00332 return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp));
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 static char* split_dname(char *device, int *unitp){
00345 char *cp;
00346 char *eos;
00347 int unit;
00348
00349
00350
00351
00352 cp = device + strlen(device) - 1;
00353 if (*cp < '0' || *cp > '9') {
00354 printf("%s missing unit number", device);
00355 return (NULL);
00356 }
00357
00358
00359 while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
00360 cp--;
00361
00362 unit = strtol(cp, &eos, 10);
00363 if (*eos != '\0') {
00364 printf("%s bad unit number", device);
00365 return (NULL);
00366 }
00367 *unitp = unit;
00368 return (cp);
00369 }
00370
00371
00372
00373
00374 static int dlattachreq(int fd, u_int32 ppa){
00375 dl_attach_req_t req;
00376
00377 req.dl_primitive = DL_ATTACH_REQ;
00378 req.dl_ppa = ppa;
00379
00380 return (send_request(fd, (char *)&req, sizeof(req), "attach"));
00381 }
00382
00383
00384
00385
00386
00387 static int dlokack(int fd, const char *what, char *bufp){
00388 return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp));
00389 }
00390
00391
00392
00393
00394 static int dlbindreq(int fd, u_int32 sap){
00395 dl_bind_req_t req;
00396
00397 memset((char *)&req, 0, sizeof(req));
00398 req.dl_primitive = DL_BIND_REQ;
00399 req.dl_sap = sap;
00400 #ifdef DL_CLDLS
00401 req.dl_service_mode = DL_CLDLS;
00402 #endif
00403
00404 return (send_request(fd, (char *)&req, sizeof(req), "bind"));
00405 }
00406
00407
00408
00409
00410 static int dlbindack(int fd, char *bufp){
00411
00412 return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp));
00413 }
00414
00415
00416
00417
00418 static int dlpromisconreq(int fd, u_int32 level){
00419 dl_promiscon_req_t req;
00420
00421 req.dl_primitive = DL_PROMISCON_REQ;
00422 req.dl_level = level;
00423
00424 return (send_request(fd, (char *)&req, sizeof(req), "promiscon"));
00425 }
00426
00427
00428
00429
00430 static int strioctl(int fd, int cmd, int len, char *dp){
00431 struct strioctl str;
00432 int rc;
00433
00434 str.ic_cmd = cmd;
00435 str.ic_timout = -1;
00436 str.ic_len = len;
00437 str.ic_dp = dp;
00438 rc = ioctl(fd, I_STR, &str);
00439
00440 if (rc < 0)
00441 return (rc);
00442 else
00443 return (str.ic_len);
00444 }
00445
00446
00447
00448
00449
00450 static char* get_release(u_int32 *majorp, u_int32 *minorp, u_int32 *microp){
00451 char *cp;
00452 static char buf[32];
00453
00454 *majorp = 0;
00455 *minorp = 0;
00456 *microp = 0;
00457 if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
00458 return ("?");
00459 cp = buf;
00460 if (!isdigit((unsigned char)*cp))
00461 return (buf);
00462 *majorp = strtol(cp, &cp, 10);
00463 if (*cp++ != '.')
00464 return (buf);
00465 *minorp = strtol(cp, &cp, 10);
00466 if (*cp++ != '.')
00467 return (buf);
00468 *microp = strtol(cp, &cp, 10);
00469 return (buf);
00470 }
00471
00472
00473
00474
00475 int OpenInterfaceSolarisDLPI(int InterfaceID){
00476 register char *cp;
00477 int ppa;
00478 register dl_info_ack_t *infop;
00479 u_int32 ss, flag;
00480 register char *release;
00481 u_int32 osmajor, osminor, osmicro;
00482 u_int32 buf[MAXDLBUF];
00483 char dname[100];
00484 char dname2[100];
00485
00486 InterfaceRec* interface;
00487
00488 interface=&Globals.Interfaces[InterfaceID];
00489
00490
00491
00492
00493 cp = split_dname(interface->Name, &ppa);
00494 if (cp == NULL){
00495 printf("I couldn't understand the interface name\n");
00496 return FALSE;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505 if (*interface->Name == '/')
00506 strncpy(dname, interface->Name, sizeof(dname));
00507 else
00508 snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
00509 interface->Name);
00510
00511
00512
00513
00514
00515 strncpy(dname2, dname, sizeof(dname));
00516 *(dname + strlen(dname) - strlen(cp)) = '\0';
00517
00518
00519 if ((interface->FD = open(dname, O_RDWR)) < 0) {
00520 if (errno != ENOENT) {
00521 printf("%s: %s", dname, strerror(errno));
00522 return FALSE;
00523 }
00524
00525
00526 if ((interface->FD = open(dname2, O_RDWR)) < 0) {
00527 printf("%s: %s", dname2, strerror(errno));
00528 return FALSE;
00529 }
00530
00531 ppa = 0;
00532 }
00533
00534
00535
00536
00537 if (dlinforeq(interface->FD) < 0 ||
00538 dlinfoack(interface->FD, (char *)buf) < 0)
00539 return FALSE;
00540 infop = &((union DL_primitives *)buf)->info_ack;
00541 if (infop->dl_provider_style == DL_STYLE2 &&
00542 (dlattachreq(interface->FD, ppa) < 0 ||
00543 dlokack(interface->FD, "attach", (char *)buf) < 0))
00544 return FALSE;
00545
00546
00547
00548
00549
00550
00551 if (dlbindreq(interface->FD, 0) < 0 ||
00552 dlbindack(interface->FD, (char *)buf) < 0)
00553 return FALSE;
00554
00555
00556 if (dlpromisconreq(interface->FD, DL_PROMISC_PHYS) < 0 ||
00557 dlokack(interface->FD, "promisc_phys", (char *)buf) < 0)
00558 return FALSE;
00559
00560
00561
00562
00563
00564
00565 if (dlpromisconreq(interface->FD, DL_PROMISC_MULTI) < 0 ||
00566 dlokack(interface->FD, "promisc_multi", (char *)buf) < 0)
00567 printf("WARNING: DL_PROMISC_MULTI failed\n");
00568
00569
00570
00571
00572
00573 if ((dlpromisconreq(interface->FD, DL_PROMISC_SAP) < 0 ||
00574 dlokack(interface->FD, "promisc_sap", (char *)buf) < 0)) {
00575
00576 printf("WARNING: DL_PROMISC_SAP failed\n");
00577 }
00578
00579
00580
00581
00582 if (strioctl(interface->FD, DLIOCRAW, 0, NULL) < 0) {
00583 printf("DLIOCRAW: %s", strerror(errno));
00584 return FALSE;
00585 }
00586
00587
00588
00589
00590 if (ioctl(interface->FD, I_PUSH, "bufmod") != 0) {
00591 printf("I_PUSH bufmod: %s", strerror(errno));
00592 return FALSE;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 ss = 1600;
00606 release = get_release(&osmajor, &osminor, &osmicro);
00607 if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
00608 getenv("BUFMOD_FIXED") == NULL) {
00609 fprintf(stderr,
00610 "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n",
00611 release);
00612 ss = 0;
00613 }
00614 if (ss > 0 &&
00615 strioctl(interface->FD, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
00616 printf("SBIOCSSNAP: %s", strerror(errno));
00617 return FALSE;
00618 }
00619
00620
00621
00622
00623 if (strioctl(interface->FD, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) {
00624 printf("SBIOCGFLAGS: %s", strerror(errno));
00625 return FALSE;
00626 }
00627 flag |= SB_NO_DROPS;
00628 if (strioctl(interface->FD, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) {
00629 printf("SBIOCSFLAGS: %s", strerror(errno));
00630 return FALSE;
00631 }
00632
00633
00634
00635
00636 if (ioctl(interface->FD, I_FLUSH, FLUSHR) != 0) {
00637 printf("FLUSHR: %s", strerror(errno));
00638 return FALSE;
00639 }
00640
00641 interface->IsPollable=TRUE;
00642
00643 return TRUE;
00644 }
00645
00646
00647
00648
00649 int ReadPacketSolarisDLPI(int InterfaceID){
00650 InterfaceRec* Interface;
00651 int PacketSlot;
00652 PacketRec* p;
00653
00654 register int cc, n, caplen, origlen;
00655 register u_char *bp, *ep, *pk;
00656 register struct sb_hdr *sbp;
00657 struct sb_hdr sbhdr;
00658 int flags;
00659 struct strbuf data;
00660
00661 static char readbuff[MAXDLBUF];
00662
00663 #ifdef DEBUGPATH
00664 printf("In ReadPacketSolarisDLPI\n");
00665 #endif
00666
00667 Interface=&Globals.Interfaces[InterfaceID];
00668
00669 flags = 0;
00670 cc=0;
00671
00672 data.buf = (char *)readbuff;
00673 data.maxlen = MAXDLBUF;
00674 data.len = 0;
00675 do {
00676 if (getmsg(Interface->FD, &ctl, &data, &flags) < 0) {
00677
00678 if (errno == EINTR) {
00679 cc = 0;
00680 continue;
00681 }
00682 return FALSE;
00683 }
00684 cc = data.len;
00685 } while (cc == 0);
00686 bp = readbuff;
00687
00688
00689 ep = bp + cc;
00690 n = 0;
00691 while (bp < ep) {
00692
00693 if ((long)bp & 3) {
00694 sbp = &sbhdr;
00695 memcpy(sbp, bp, sizeof(*sbp));
00696 } else
00697 sbp = (struct sb_hdr *)bp;
00698
00699 pk = bp + sizeof(*sbp);
00700 bp += sbp->sbh_totlen;
00701 origlen = sbp->sbh_origlen;
00702 caplen = sbp->sbh_msglen;
00703
00704
00705 if ( (PacketSlot=GetEmptyPacket())==-1){
00706 printf("Unable to allocate packet for reading\n");
00707 return FALSE;
00708 }
00709 p=&Globals.Packets[PacketSlot];
00710 p->InterfaceNum=InterfaceID;
00711 p->PacketLen=sbp->sbh_msglen;
00712 p->tv=sbp->sbh_timestamp;
00713 memcpy(p->RawPacket, ((char*)sbp)+sizeof(struct sb_hdr), p->PacketLen);
00714
00715 if (!AddPacketToPending(PacketSlot)){
00716 printf("Couldn't add packet to pending queue\n");
00717 ReturnEmptyPacket(PacketSlot);
00718 return FALSE;
00719 }
00720
00721
00722 }
00723
00724 return TRUE;
00725 }
00726
00727
00728
00729
00730 int WritePacketSolarisDLPI(int InterfaceID, unsigned char* Packet, int PacketLen){
00731 InterfaceRec* interface;
00732 #ifdef DEBUGPATH
00733 printf("In WritePacketSolarisDLPI\n");
00734 #endif
00735
00736 interface=&Globals.Interfaces[InterfaceID];
00737
00738
00739 return TRUE;
00740 }
00741
00742
00743
00744
00745 void* SolarisDLPILoopFunc(void* v){
00746 int InterfaceID;
00747
00748 #ifdef DEBUGPATH
00749 printf("In SolarisDLPILoopFunc\n");
00750 #endif
00751
00752 InterfaceID=(int)v;
00753 while (!Globals.Done){
00754 ReadPacketSolarisDLPI(InterfaceID);
00755 }
00756
00757 return NULL;
00758 }
00759
00760
00761
00762
00763 int LoopThreadSolarisDLPI(int InterfaceID){
00764 #ifdef DEBUGPATH
00765 printf("In loopThreadSolarisDLPI\n");
00766 #endif
00767
00768 #ifndef HAS_THREADS
00769 return FALSE;
00770 #else
00771
00772 #ifdef DEBUG
00773 printf("Starting Thread for interface %s\n",Globals.Interfaces[InterfaceID].Name);
00774 #endif
00775
00776 Globals.Interfaces[InterfaceID].ThreadID=pthread_create(
00777 &Globals.Interfaces[InterfaceID].Thread,
00778 NULL,
00779 SolarisDLPILoopFunc,
00780 (void*)InterfaceID
00781 );
00782
00783 return (!Globals.Interfaces[InterfaceID].ThreadID);
00784 #endif
00785
00786 }
00787
00788 #endif