1 #define _XOPEN_SOURCE 500
2 #include <ftw.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 static char interface_match[32];
8 static char interface_address[13];
9 static char interface_slot[13]="not found";
10 
11 static int
find_slot(const char * fpath,const struct stat * sb,int tflag,struct FTW * ftwbuf)12 find_slot(const char *fpath, const struct stat *sb,
13 	  int tflag, struct FTW *ftwbuf)
14 {
15   char slot_address[11];
16   int  ret;
17   FILE *address_file;
18   char *myfpath;
19   char *this_tok;
20   char *last_tok = NULL;
21 
22   /* so, are we at a point in the tree where the basename is
23      "address" ? */
24   if (strcmp("address",fpath + ftwbuf->base) == 0) {
25     address_file = fopen(fpath,"r");
26     if (address_file == NULL) {
27       strcpy(interface_slot,"fopen");
28       return 0;
29     }
30     /* we make the simplifying assumption that PCI domain, bus, slot
31        and function, with associated separators, are 10 characters or
32        less */
33     ret = fread(slot_address,1,10,address_file);
34     if (ret != 10) {
35       strcpy(interface_slot,"fread");
36       fclose(address_file);
37       return 0;
38     }
39     slot_address[ret] = 0;
40     /* the slot address will be a substring of the full bus address of
41        the interface we seek */
42     if (strstr(interface_address,slot_address)) {
43 	myfpath = strdup(fpath);
44 	if (myfpath == NULL) {
45 	  strcpy(interface_slot,"strcpy");
46 	  return 1;
47 	}
48 
49 	this_tok = strtok(myfpath,"/");
50 	while (strcmp(this_tok,"address")) {
51 	  last_tok = this_tok;
52 	  this_tok = strtok(NULL,"/");
53 	}
54 	if (last_tok != NULL)
55 	  strcpy(interface_slot,last_tok);
56 	else
57 	  strcpy(interface_slot,"last_tok");
58 	free(myfpath);
59 	fclose(address_file);
60 	return 1;
61     }
62     fclose(address_file);
63   }
64   return 0;
65 }
66 
67 static int
find_interface(const char * fpath,const struct stat * sb,int tflag,struct FTW * ftwbuf)68 find_interface(const char *fpath, const struct stat *sb,
69 	       int tflag, struct FTW *ftwbuf)
70 {
71   char *myfpath;
72   char *this_tok;
73   char *last_tok = NULL;
74 
75   if (strcmp(interface_match,fpath + ftwbuf->base) == 0) {
76     myfpath = strdup(fpath);
77     if (myfpath == NULL) {
78       strcpy(interface_address,"strcpy");
79       return 1;
80     }
81     this_tok = strtok(myfpath,"/");
82     while (strcmp(this_tok,interface_match)) {
83       last_tok = this_tok;
84       this_tok = strtok(NULL,"/");
85     }
86     if (last_tok != NULL)
87       strcpy(interface_address,last_tok);
88     else
89       strcpy(interface_address,"last_tok");
90     free(myfpath);
91     return 1;
92   }
93   return 0;
94 }
95 
96 char *
find_interface_slot(char * interface_name)97 find_interface_slot(char *interface_name) {
98 
99   int flags = 0;
100   int ret;
101 
102   flags |= FTW_PHYS;  /* don't follow symlinks for they will lead us
103 			 off the path */
104   ret = snprintf(interface_match,31,"net:%s",interface_name);
105   interface_match[31]=0;
106   /* having setup the basename we will be seeking, go find it and the
107      corresponding interface_address */
108   nftw("/sys/devices", find_interface, 20, flags);
109   /* now that we ostensibly have the pci address of the interface
110      (interface_address, lets find that slot shall we? */
111   nftw("/sys/bus/pci/slots", find_slot, 20, flags);
112   return strdup(interface_slot);
113 }
114 
115 static int
get_val_from_file(char * valsource)116 get_val_from_file(char *valsource) {
117   FILE *valfile;
118   char buffer[6]; /* 0xabcd */
119   int ret;
120 
121   valfile = fopen(valsource,"r");
122   if (valfile == NULL) return -1;
123 
124   ret = fread(buffer,1,sizeof(buffer), valfile);
125   if (ret != sizeof(buffer)) {
126     fclose(valfile);
127     return -1;
128   }
129 
130   ret = (int)strtol(buffer,NULL,0);
131 
132   fclose(valfile);
133   return ret;
134 
135 }
136 
137 void
find_interface_ids(char * interface_name,int * vendor,int * device,int * sub_vend,int * sub_dev)138 find_interface_ids(char *interface_name, int *vendor, int *device, int *sub_vend, int *sub_dev) {
139 
140   int ret;
141 
142   char sysfile[128];  /* gotta love constants */
143 
144   /* first the vendor id */
145   ret = snprintf(sysfile,128,"/sys/class/net/%s/device/vendor",interface_name);
146   *vendor = get_val_from_file(sysfile);
147 
148   /* next the device */
149   ret = snprintf(sysfile,128,"/sys/class/net/%s/device/device",interface_name);
150   *device = get_val_from_file(sysfile);
151 
152   /* next the subsystem vendor */
153   ret = snprintf(sysfile,128,"/sys/class/net/%s/device/subsystem_vendor",interface_name);
154   *sub_vend = get_val_from_file(sysfile);
155 
156   /* next the subsystem device */
157   ret = snprintf(sysfile,128,"/sys/class/net/%s/device/subsystem_device",interface_name);
158   *sub_dev = get_val_from_file(sysfile);
159 
160 }
161 
162 
163 
164 
165 
166