1 /* ripng.c - RIPng (version 1) code for sendip
2  * Created by hacking rip code
3  * ChangeLog since 2.2 release:
4  * 15/10/2002 Read the spec
5  * 24/11/2002 Made it compile on archs needing alignment
6  */
7 
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include "sendip_module.h"
16 #include "ripng.h"
17 
18 /* Character that identifies our options
19  */
20 const char opt_char='R';
21 
inet6_addr(char * hostname)22 static struct in6_addr inet6_addr(char *hostname) {
23 	struct hostent *host = gethostbyname2(hostname,AF_INET6);
24 	struct in6_addr ret;
25 	if(host==NULL) {
26 		fprintf(stderr,"RIPNG: Couldn't get address for %s defaulting to loopback",hostname);
27 		return in6addr_loopback;
28 	}
29 	if(host->h_length != sizeof(struct in6_addr)) {
30 		fprintf(stderr,"RIPNG: IPV6 address is the wrong size: defaulting to loopback");
31 		return in6addr_loopback;
32 	}
33 	memcpy(&ret,host->h_addr,sizeof(ret));
34 	return ret;
35 }
36 
initialize(void)37 sendip_data *initialize(void) {
38 	sendip_data *ret = malloc(sizeof(sendip_data));
39 	ripng_header *rip = malloc(sizeof(ripng_header));
40 	memset(rip,0,sizeof(ripng_header));
41 	ret->alloc_len = sizeof(ripng_header);
42 	ret->data = (void *)rip;
43 	ret->modified=0;
44 	return ret;
45 }
46 
do_opt(char * opt,char * arg,sendip_data * pack)47 bool do_opt(char *opt, char *arg, sendip_data *pack) {
48 	ripng_header *rippack = (ripng_header *)pack->data;
49 	ripng_entry *ripopt;
50 	char *p, *q;
51 	switch(opt[1]) {
52 	case 'v': /* version */
53 		rippack->version = (u_int8_t)strtoul(arg, (char **)0, 0);
54 		pack->modified |= RIPNG_MOD_VERSION;
55 		break;
56 	case 'c': /* command */
57 		rippack->command = (u_int8_t)strtoul(arg, (char **)0, 0);
58 		pack->modified |= RIPNG_MOD_COMMAND;
59 		break;
60 	case 'r': /* reserved */
61 		rippack->res = htons((u_int16_t)strtoul(arg, (char **)0, 0));
62 		pack->modified |= RIPNG_MOD_RESERVED;
63 		break;
64 		/*
65 	case 'a': / * authenticate * /
66 		if(RIPNG_NUM_ENTRIES(pack) != 0) {
67 			usage_error("Warning: a real RIP-2 packet only has authentication on the first entry.\n");
68 		}
69 		pack->modified |= RIP_IS_AUTH;
70 		pack->data = realloc(pack->data,pack->alloc_len+strlen(arg));
71 		strcpy(pack->data+pack->alloc_len,arg);
72 		pack->alloc_len += strlen(arg);
73 		break;
74 		*/
75 	case 'e': /* rip entry */
76 		RIPNG_ADD_ENTRY(pack);
77 		ripopt = RIPNG_ENTRY(pack);
78 		p=q=arg;
79 		/* TODO: if arg is malformed, this could segfault */
80 		while(*(q++)!='/') /* do nothing */; *(--q)='\0';
81 		ripopt->prefix = (p==q)?in6addr_any:inet6_addr(p);
82 
83 		p=++q; while(*(q++)!='/') /* do nothing */; *(--q)='\0';
84 		ripopt->tag=htons( (p==q)?0:(u_int16_t)strtoul(p, (char **)0,0));
85 
86 		p=++q; while(*(q++)!='/') /* do nothing */; *(--q)='\0';
87 		ripopt->len=(p==q)?(u_int8_t)128:(u_int8_t)strtoul(p, (char **)0,0);
88 
89 		p=++q; while(*(q++)!='\0') /* do nothing */; *(--q)='\0';
90 		ripopt->metric=(p==q)?(u_int8_t)16:(u_int8_t)strtoul(p,(char **)0, 0);
91 		break;
92 	case 'd': /* default request */
93 		if(RIPNG_NUM_ENTRIES(pack) != 0) {
94 			usage_error("Warning: a real RIPng packet does not have any other entries in a default request.\n");
95 		}
96 		rippack->command = (u_int8_t)1;
97 		rippack->version = (u_int8_t)1;
98 		rippack->res = (u_int16_t)0;
99 		pack->modified|=RIPNG_MOD_COMMAND|RIPNG_MOD_VERSION|RIPNG_MOD_RESERVED;
100 		RIPNG_ADD_ENTRY(pack);
101 		ripopt=RIPNG_ENTRY(pack);
102 		ripopt->prefix=in6addr_any;
103 		ripopt->tag=(u_int16_t)0;
104 		ripopt->len=(u_int8_t)0;
105 		ripopt->metric=htons((u_int16_t)16);
106 		break;
107 	}
108 	return TRUE;
109 
110 }
111 
finalize(char * hdrs,sendip_data * headers[],sendip_data * data,sendip_data * pack)112 bool finalize(char *hdrs, sendip_data *headers[], sendip_data *data,
113 				  sendip_data *pack) {
114 	if(hdrs[strlen(hdrs)-1] != 'u') {
115 		usage_error("Warning: RIPng should be contained in a UDP packet\n");
116 	}
117 
118 	return TRUE;
119 }
120 
num_opts()121 int num_opts() {
122 	return sizeof(rip_opts)/sizeof(sendip_option);
123 }
get_opts()124 sendip_option *get_opts() {
125 	return rip_opts;
126 }
get_optchar()127 char get_optchar() {
128 	return opt_char;
129 }
130