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