Usermode - Fixing build system
[tpg/acess2.git] / Usermode / Applications / ifconfig_src / main.c
1 /*
2  * Acess2 IFCONFIG command
3  */
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <acess/sys.h>
9 #include <net.h>
10
11 // === CONSTANTS ===
12 #define FILENAME_MAX    255
13 #define IPSTACK_ROOT    "/Devices/ip"
14 #define DEFAULT_METRIC  30
15
16 // TODO: Move this to a header
17 #define ntohs(v)        (((v&0xFF)<<8)|((v>>8)&0xFF))
18
19 // === PROTOTYPES ===
20 void    PrintUsage(const char *ProgName);
21 void    DumpInterfaces(void);
22 void    DumpRoutes(void);
23 void    DumpInterface(const char *Name);
24 void    DumpRoute(const char *Name);
25  int    AddInterface(const char *Device);
26 void    AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop);
27  int    DoAutoConfig(const char *Device);
28  int    SetAddress(int IFNum, const char *Address);
29  int    ParseIPAddress(const char *Address, uint8_t *Dest, int *SubnetBits);
30
31 // === CODE ===
32 /**
33  * \brief Program entrypoint
34  */
35 int main(int argc, char *argv[])
36 {
37          int    ret;
38         
39         // No args, dump interfaces
40         if(argc == 1) {
41                 DumpInterfaces();
42                 return 0;
43         }
44         
45         // Routes
46         if( strcmp(argv[1], "route") == 0 )
47         {
48                 // Add new route
49                 if( argc > 2 && strcmp(argv[2], "add") == 0 )
50                 {
51                         uint8_t dest[16] = {0};
52                         uint8_t nextHop[16] = {0};
53                          int    addrType, subnetBits = -1;
54                          int    nextHopType, nextHopBits=-1;
55                         char    *ifaceName = NULL;
56                          int    metric = DEFAULT_METRIC;
57                         // Usage:
58                         // ifconfig route add <host>[/<prefix>] <interface> [<metric>]
59                         // ifconfig route add <host>[/<prefix>] <next hop> [<metric>]
60                         if( argc - 3  < 2 ) {
61                                 fprintf(stderr, "ERROR: '%s route add' takes at least two arguments, %i passed\n",
62                                         argv[0], argc-3);
63                                 PrintUsage(argv[0]);
64                                 return -1;
65                         }
66                         
67                         if( argc - 3 > 3 ) {
68                                 fprintf(stderr, "ERROR: '%s route add' takes at most three arguments, %i passed\n",
69                                         argv[0], argc-3);
70                                 PrintUsage(argv[0]);
71                                 return -1;
72                         }
73                         
74                         // Destination IP
75                         addrType = ParseIPAddress(argv[3], dest, &subnetBits);
76                         if( subnetBits == -1 ) {
77                                 subnetBits = Net_GetAddressSize(addrType)*8;
78                         }
79                         // Interface Name / Next Hop
80                         if( (nextHopType = ParseIPAddress(argv[4], nextHop, &nextHopBits)) == 0 )
81                         {
82                                 // Interface name
83                                 ifaceName = argv[4];
84                         }
85                         else
86                         {
87                                 // Next Hop
88                                 // - Check if it's the same type as the network/destination
89                                 if( nextHopType != addrType ) {
90                                         fprintf(stderr, "ERROR: Address type mismatch\n");
91                                         return -1;
92                                 }
93                                 // - Make sure there's no mask
94                                 if( nextHopBits != -1 ) {
95                                         fprintf(stderr, "Error: Next hop cannot be masked\n");
96                                         return -1;
97                                 }
98                         }
99                         
100                         // Metric
101                         if( argc - 3 >= 3 )
102                         {
103                                 metric = atoi(argv[5]);
104                                 if( metric == 0 && argv[5][0] != '0' ) {
105                                         fprintf(stderr, "ERROR: Metric should be a number\n");
106                                         return -1;
107                                 }
108                         }
109                         
110                         // Make the route!
111                         AddRoute(ifaceName, addrType, dest, subnetBits, metric, nextHop);
112                         
113                         return 0;
114                 }
115                 // Delete a route
116                 else if( argc > 2 && strcmp(argv[2], "del") == 0 )
117                 {
118                         // Usage:
119                         // ifconfig route del <routenum>
120                         // ifconfig route del <host>[/<prefix>]
121                 }
122                 else
123                 {
124                         // List routes
125                         DumpRoutes();
126                 }
127                 return 0;
128         }
129         // Add a new interface
130         else if( strcmp(argv[1], "add") == 0 )
131         {
132                 if( argc < 4 ) {
133                         fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2);
134                         PrintUsage(argv[0]);
135                         return -1;
136                 }
137                 // TODO: Also set the IP address as the usage says it does
138                 ret = AddInterface( argv[2] );
139                 if(ret < 0)     return ret;
140                 ret = SetAddress( ret, argv[3] );
141                 return ret;
142         }
143         // Delete an interface
144         else if( strcmp(argv[1], "del") == 0 )
145         {
146                 if( argc < 3 ) {
147                         fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]);
148                         PrintUsage(argv[0]);
149                         return -1;
150                 }
151                 // TODO:
152         }
153         // Autoconfigure an interface
154         // NOTE: Debugging hack (see the function for more details)
155         else if( strcmp(argv[1], "autoconf") == 0 )
156         {
157                 DoAutoConfig(argv[2]);
158                 return 0;
159         }
160         else if( strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 )
161         {
162                 PrintUsage(argv[0]);
163                 return 0;
164         }
165         
166         // Dump a named interface
167         DumpInterface(argv[1]);
168         
169         return 0;
170 }
171
172 /**
173  * \brief Print usage instructions
174  */
175 void PrintUsage(const char *ProgName)
176 {
177         fprintf(stderr, "Usage:\n");
178         fprintf(stderr, "    %s add <device> <ip>/<prefix>\n", ProgName);
179         fprintf(stderr, "        Add a new interface listening on <device> with the specified\n");
180         fprintf(stderr, "        address.\n");
181         fprintf(stderr, "    %s del <interface>\n", ProgName);
182         fprintf(stderr, "        Delete an interface\n");
183         fprintf(stderr, "    %s [<interface>]\n", ProgName);
184         fprintf(stderr, "        Print the current interfaces (or only <interface> if passed)\n");
185         fprintf(stderr, "\n");
186         fprintf(stderr, "    %s route\n", ProgName);
187         fprintf(stderr, "        Print the routing tables\n");
188         fprintf(stderr, "    %s route add <host>[/<prefix>] [<nexthop> OR <iface>] [<metric>]\n", ProgName);
189         fprintf(stderr, "        Add a new route\n");
190         fprintf(stderr, "    %s route del <host>[/<prefix>]\n", ProgName);
191         fprintf(stderr, "    %s route del <routenum>\n", ProgName);
192         fprintf(stderr, "        Add a new route\n");
193         fprintf(stderr, "\n");
194         fprintf(stderr, "A note on Acess's IP Stack:\n");
195         fprintf(stderr, "    Each interface corresponds to only one IP address (either IPv4\n");
196         fprintf(stderr, "    or IPv6). A network device can have multiple interfaces bound\n");
197         fprintf(stderr, "    to it, allowing multiple addresses for one network connection\n");
198         fprintf(stderr, "\n");
199 }
200
201 /**
202  * \brief Dump all interfaces
203  */
204 void DumpInterfaces(void)
205 {
206          int    dp;
207         char    filename[FILENAME_MAX+1];
208         
209         dp = open(IPSTACK_ROOT, OPENFLAG_READ);
210         
211         while( readdir(dp, filename) )
212         {
213                 if(filename[0] == '.')  continue;
214                 DumpInterface(filename);
215         }
216         
217         close(dp);
218 }
219
220 /**
221  * \brief Dump all interfaces
222  */
223 void DumpRoutes(void)
224 {
225          int    dp;
226         char    filename[FILENAME_MAX+1];
227         
228         dp = open(IPSTACK_ROOT"/routes", OPENFLAG_READ);
229         
230         printf("ID\tType\tNetwork \tGateway \tMetric\tIFace\n");
231         
232         while( readdir(dp, filename) )
233         {
234                 if(filename[0] == '.')  continue;
235                 DumpRoute(filename);
236         }
237         
238         close(dp);
239 }
240
241 /**
242  * \brief Dump an interface
243  */
244 void DumpInterface(const char *Name)
245 {
246          int    fd;
247          int    type;
248         char    path[sizeof(IPSTACK_ROOT)+1+FILENAME_MAX+1] = IPSTACK_ROOT"/";
249         
250         strcat(path, Name);
251         
252         fd = open(path, OPENFLAG_READ);
253         if(fd == -1) {
254                 fprintf(stderr, "Bad interface name '%s' (%s does not exist)\t", Name, path);
255                 return ;
256         }
257         
258         type = ioctl(fd, 4, NULL);
259         
260         // Ignore -1 values
261         if( type == -1 ) {
262                 return ;
263         }
264         
265         printf("%s:\t", Name);
266         {
267                  int    call_num = ioctl(fd, 3, "get_device");
268                  int    len = ioctl(fd, call_num, NULL);
269                 char    *buf = malloc(len+1);
270                 ioctl(fd, call_num, buf);
271                 printf("'%s'\n", buf);
272                 free(buf);
273         }
274         printf("\t");
275         // Get the address type
276         switch(type)
277         {
278         case 0: // Disabled/Unset
279                 printf("DISABLED\n");
280                 break;
281         case 4: // IPv4
282                 {
283                 uint8_t ip[4];
284                  int    subnet;
285                 printf("IPv4\t");
286                 ioctl(fd, 5, ip);       // Get IP Address
287                 subnet = ioctl(fd, 7, NULL);    // Get Subnet Bits
288                 printf("%i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet);
289                 }
290                 break;
291         case 6: // IPv6
292                 {
293                 uint16_t        ip[8];
294                  int    subnet;
295                 printf("IPv6\t");
296                 ioctl(fd, 5, ip);       // Get IP Address
297                 subnet = ioctl(fd, 7, NULL);    // Get Subnet Bits
298                 printf("%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
299                         ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
300                         ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]),
301                         subnet);
302                 }
303                 break;
304         default:        // Unknow
305                 printf("UNKNOWN (%i)\n", type);
306                 break;
307         }
308                         
309         close(fd);
310 }
311
312
313 /**
314  * \brief Dump a route
315  */
316 void DumpRoute(const char *Name)
317 {
318          int    fd;
319          int    type;
320         char    path[sizeof(IPSTACK_ROOT)+8+FILENAME_MAX+1] = IPSTACK_ROOT"/routes/";
321         
322         strcat(path, Name);
323         
324         fd = open(path, OPENFLAG_READ);
325         if(fd == -1) {
326                 printf("%s:\tUnable to open ('%s')\n", Name, path);
327                 return ;
328         }
329         
330         type = ioctl(fd, 4, NULL);
331         
332         // Ignore -1 values
333         if( type == -1 ) {
334                 return ;
335         }
336         
337         // Number
338         printf("%s\t", Name);
339         
340         // Get the address type
341         switch(type)
342         {
343         case 0: // Disabled/Unset
344                 printf("DISABLED\n");
345                 break;
346         case 4: // IPv4
347                 {
348                 uint8_t net[4], addr[4];
349                  int    subnet, metric;
350                 printf("IPv4\t");
351                 ioctl(fd, ioctl(fd, 3, "get_network"), net);    // Get Network
352                 ioctl(fd, ioctl(fd, 3, "get_nexthop"), addr);   // Get Gateway/NextHop
353                 subnet = ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), NULL);    // Get Subnet Bits
354                 metric = ioctl(fd, ioctl(fd, 3, "getset_metric"), NULL);        // Get Subnet Bits
355                 printf("%s/%i\t", Net_PrintAddress(4, net), subnet);
356                 printf("%s \t", Net_PrintAddress(4, addr));
357                 printf("%i\t", metric);
358                 }
359                 break;
360         case 6: // IPv6
361                 {
362                 uint16_t        net[8], addr[8];
363                  int    subnet, metric;
364                 printf("IPv6\t");
365                 ioctl(fd, ioctl(fd, 3, "get_network"), net);    // Get Network
366                 ioctl(fd, ioctl(fd, 3, "get_nexthop"), addr);   // Get Gateway/NextHop
367                 subnet = ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), NULL);    // Get Subnet Bits
368                 metric = ioctl(fd, ioctl(fd, 3, "getset_metric"), NULL);        // Get Subnet Bits
369                 printf("%s/%i\t", Net_PrintAddress(6, net), subnet);
370                 printf("%s\t", Net_PrintAddress(6, addr));
371                 printf("%i\t", metric);
372                 }
373                 break;
374         default:        // Unknow
375                 printf("UNKNOWN (%i)\n", type);
376                 break;
377         }
378         
379         // Interface
380         {
381                  int    call_num = ioctl(fd, 3, "get_interface");
382                  int    len = ioctl(fd, call_num, NULL);
383                 char    *buf = malloc(len+1);
384                 ioctl(fd, call_num, buf);
385                 printf("'%s'\t", buf);
386                 free(buf);
387         }
388         
389         printf("\n");
390                         
391         close(fd);
392 }
393
394 /**
395  * \brief Create a new interface using the passed device
396  * \param Device        Network device to bind to
397  */
398 int AddInterface(const char *Device)
399 {
400          int    dp, ret;
401         
402         dp = open(IPSTACK_ROOT, OPENFLAG_READ);
403         ret = ioctl(dp, 4, (void*)Device);
404         close(dp);
405         
406         if( ret < 0 ) {
407                 fprintf(stderr, "Unable to add '%s' as a network interface\n", Device);
408                 return -1;
409         }
410         
411         printf("-- Added '"IPSTACK_ROOT"/%i' using device %s\n", ret, Device);
412         
413         return ret;
414 }
415
416 void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop)
417 {
418          int    fd;
419          int    num;
420         char    tmp[sizeof(IPSTACK_ROOT"/routes/") + 5];        // enough for 4 digits
421         char    *ifaceToFree = NULL;
422         
423         // Get interface name
424         if( !Interface )
425         {
426                 if( !NextHop ) {
427                         fprintf(stderr,
428                                 "BUG: AddRoute(Interface=NULL,...,NextHop=NULL)\n"
429                                 "Only one should be NULL\n"
430                                 );
431                         return ;
432                 }
433                 
434                 // Query for the interface name
435                 Interface = ifaceToFree = Net_GetInterface(AddressType, NextHop);
436         }
437         // Check address type (if the interface was passed)
438         // - If we got the interface name, then it should be correct
439         else
440         {
441                 char    ifacePath[sizeof(IPSTACK_ROOT"/")+strlen(Interface)+1];
442                 
443                 // Open interface
444                 strcpy(ifacePath, IPSTACK_ROOT"/");
445                 strcat(ifacePath, Interface);
446                 fd = open(ifacePath, 0);
447                 if( fd == -1 ) {
448                         fprintf(stderr, "Error: Interface '%s' does not exist\n", Interface);
449                         return ;
450                 }
451                 // Get and check type
452                 num = ioctl(fd, ioctl(fd, 3, "getset_type"), NULL);
453                 if( num != AddressType ) {
454                         fprintf(stderr, "Error: Passed type does not match interface type (%i != %i)\n",
455                                 AddressType, num);
456                         return ;
457                 }
458                 
459                 close(fd);
460         }
461         
462         // Create route
463         fd = open(IPSTACK_ROOT"/routes", 0);
464         num = ioctl(fd, ioctl(fd, 3, "add_route"), (char*)Interface);
465         close(fd);
466         
467         // Open route
468         sprintf(tmp, IPSTACK_ROOT"/routes/%i", num);
469         fd = open(tmp, 0);
470         
471         ioctl(fd, ioctl(fd, 3, "set_network"), Dest);
472         if( NextHop )
473                 ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
474         ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), &MaskBits);
475         ioctl(fd, ioctl(fd, 3, "getset_metric"), &Metric);
476         
477         close(fd);
478         
479         // Check if the interface name was allocated by us
480         if( ifaceToFree )
481                 free(ifaceToFree);
482 }
483
484 /**
485  * \note Debugging HACK!
486  * \brief Autoconfigure the specified device to 10.0.2.55/8 using
487  *        10.0.2.1 as the gateway.
488  */
489 int DoAutoConfig(const char *Device)
490 {
491          int    tmp, fd;
492         char    path[sizeof(IPSTACK_ROOT)+1+4+1];       // /0000
493         uint8_t addr[4] = {10,0,2,55};
494         uint8_t gw[4] = {10,0,2,2};
495          int    subnet = 24;
496         
497         tmp = AddInterface(Device);
498         if( tmp < 0 )   return tmp;
499         
500         sprintf(path, IPSTACK_ROOT"/%i", tmp);
501         
502         fd = open(path, OPENFLAG_READ);
503         if( fd == -1 ) {
504                 fprintf(stderr, "Unable to open '%s'\n", path);
505                 return -1;
506         }
507         
508         tmp = 4;        // IPv4
509         tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
510         if( tmp != 4 ) {
511                 fprintf(stderr, "Error in setting address type (got %i, expected 4)\n", tmp);
512                 return -1;
513         }
514         // Set Address
515         ioctl(fd, ioctl(fd, 3, "set_address"), addr);
516         // Set Subnet
517         ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
518         
519         // Set routes
520         {
521                 uint8_t net[4] = {0,0,0,0};
522                 AddRoute(path + sizeof(IPSTACK_ROOT), 4, addr, subnet, DEFAULT_METRIC, net);    // This interface
523                 AddRoute(path + sizeof(IPSTACK_ROOT), 4, net, 0, DEFAULT_METRIC, gw);   // Gateway
524         }
525         
526         close(fd);
527         
528         printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n",
529                 addr[0], addr[1], addr[2], addr[3],
530                 subnet,
531                 gw[0], gw[1], gw[2], gw[3]);
532         
533         return 0;
534 }
535
536 /**
537  * \brief Set the address on an interface from a textual IP address
538  */
539 int     SetAddress(int IFNum, const char *Address)
540 {
541         uint8_t addr[16];
542          int    type;
543         char    path[sizeof(IPSTACK_ROOT)+1+5+1];       // ip000
544          int    tmp, fd, subnet;
545         
546         // Parse IP Address
547         type = ParseIPAddress(Address, addr, &subnet);
548         if(type == 0) {
549                 fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
550                 return -1;
551         }
552         
553         // Open file
554         sprintf(path, IPSTACK_ROOT"/%i", IFNum);
555         fd = open(path, OPENFLAG_READ);
556         if( fd == -1 ) {
557                 fprintf(stderr, "Unable to open '%s'\n", path);
558                 return -1;
559         }
560         
561         tmp = type;
562         tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
563         if( tmp != type ) {
564                 fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
565                 close(fd);
566                 return -1;
567         }
568         // Set Address
569         ioctl(fd, ioctl(fd, 3, "set_address"), addr);
570         
571         // Set Subnet
572         ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
573         
574         close(fd);
575         
576         // Dump!
577         //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
578         
579         return 0;
580 }
581
582 /**
583  * \brief Parse an IP Address
584  * \return 0 for unknown, 4 for IPv4 and 6 for IPv6
585  */
586 int ParseIPAddress(const char *Address, uint8_t *Dest, int *SubnetBits)
587 {
588         const char      *p = Address;
589         
590         // Check first block
591         while(*p && *p >= '0' && *p <= '9')     p ++;
592         
593         // IPv4?
594         if(*p == '.')
595         {
596                  int    i = 0, j;
597                  int    val;
598                 
599                 for( j = 0; Address[i] && j < 4; j ++ )
600                 {
601                         val = 0;
602                         for( ; '0' <= Address[i] && Address[i] <= '9'; i++ )
603                         {
604                                 val = val*10 + Address[i] - '0';
605                         }
606                         if(val > 255) {
607                                 //printf("val > 255 (%i)\n", val);
608                                 return 0;
609                         }
610                         Dest[j] = val;
611                         
612                         if(Address[i] == '.')
613                                 i ++;
614                 }
615                 if( j != 4 ) {
616                         //printf("4 parts expected, %i found\n", j);
617                         return 0;
618                 }
619                 // Parse subnet size
620                 if(Address[i] == '/') {
621                         val = 0;
622                         i ++;
623                         while('0' <= Address[i] && Address[i] <= '9') {
624                                 val *= 10;
625                                 val += Address[i] - '0';
626                                 i ++;
627                         }
628                         if(val > 32) {
629                                 printf("Notice: Subnet size >32 (%i)\n", val);
630                         }
631                         if(SubnetBits)  *SubnetBits = val;
632                 }
633                 if(Address[i] != '\0') {
634                         //printf("EOS != '\\0', '%c'\n", Address[i]);
635                         return 0;
636                 }
637                 return 4;
638         }
639         
640         // IPv6
641         if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F'))
642         {
643                  int    i = 0;
644                  int    j, k;
645                  int    val, split = -1, end;
646                 uint16_t        hi[8], low[8];
647                 
648                 for( j = 0; Address[i] && j < 8; j ++ )
649                 {
650                         if(Address[i] == '/')
651                                 break;
652                         
653                         if(Address[i] == ':') {
654                                 if(split != -1) {
655                                         printf("Two '::'s\n");
656                                         return 0;
657                                 }
658                                 split = j;
659                                 i ++;
660                                 continue;
661                         }
662                         
663                         val = 0;
664                         for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ )
665                         {
666                                 val *= 16;
667                                 if('0' <= Address[i] && Address[i] <= '9')
668                                         val += Address[i] - '0';
669                                 else if('A' <= Address[i] && Address[i] <= 'F')
670                                         val += Address[i] - 'A' + 10;
671                                 else if('a' <= Address[i] && Address[i] <= 'f')
672                                         val += Address[i] - 'a' + 10;
673                                 else {
674                                         printf("%c unexpected\n", Address[i]);
675                                         return 0;
676                                 }
677                         }
678                         
679                         if(val > 0xFFFF) {
680                                 printf("val (0x%x) > 0xFFFF\n", val);
681                                 return 0;
682                         }
683                         
684                         if(split == -1)
685                                 hi[j] = val;
686                         else
687                                 low[j-split] = val;
688                         
689                         if( Address[i] == ':' ) {
690                                 i ++;
691                         }
692                 }
693                 end = j;
694                 
695                 // Parse subnet size
696                 if(Address[i] == '/') {
697                         val = 0;
698                         while('0' <= Address[i] && Address[i] <= '9') {
699                                 val *= 10;
700                                 val += Address[i] - '0';
701                                 i ++;
702                         }
703                         if(val > 128) {
704                                 printf("Notice: Subnet size >128 (%i)\n", val);
705                         }
706                         if(SubnetBits)  *SubnetBits = val;
707                 }
708                 
709                 for( j = 0; j < split; j ++ )
710                 {
711                         //printf("%04x:", hi[j]);
712                         Dest[j*2] = hi[j]>>8;
713                         Dest[j*2+1] = hi[j]&0xFF;
714                 }
715                 for( ; j < 8 - (end - split); j++ )
716                 {
717                         //printf("0000:", hi[j]);
718                         Dest[j*2] = 0;
719                         Dest[j*2+1] = 0;
720                 }
721                 for( k = 0; j < 8; j ++, k++)
722                 {
723                         //printf("%04x:", low[k]);
724                         Dest[j*2] = low[k]>>8;
725                         Dest[j*2+1] = low[k]&0xFF;
726                 }
727                 return 6;
728         }
729         // Unknown type
730         return 0;
731 }

UCC git Repository :: git.ucc.asn.au