1    | /***************************************
2    |   $Revision: 1.5 $
3    | 
4    |   Radix payload (rp) - user level functions for storing data in radix trees
5    | 
6    |   rp_convert = conversion helpers for RX_asc_node and UD module.
7    | 
8    |   Status: NOT REVIEWED, TESTED
9    |   
10   |   Design and implementation by: Marek Bukowy
11   |   
12   |   ******************/ /******************
13   |   Copyright (c) 1999                              RIPE NCC
14   |  
15   |   All Rights Reserved
16   |   
17   |   Permission to use, copy, modify, and distribute this software and its
18   |   documentation for any purpose and without fee is hereby granted,
19   |   provided that the above copyright notice appear in all copies and that
20   |   both that copyright notice and this permission notice appear in
21   |   supporting documentation, and that the name of the author not be
22   |   used in advertising or publicity pertaining to distribution of the
23   |   software without specific, written prior permission.
24   |   
25   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
26   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
27   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
28   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31   |   ***************************************/
32   | 
33   | #include <rp.h>
34   | #include <iproutines.h>
35   | #include <rxroutines.h>
36   | 
37   | rx_fam_t RP_attr2fam( rp_attr_t type )
38   | {
39   |   switch( type ) {
40   |   case  A_RT:  return  RX_FAM_RT;
41   |   case  A_IN:  return  RX_FAM_IN;
42   |   case  A_DN:  return  RX_FAM_RT;
43   |   case  A_I6:  return  RX_FAM_RT;
44   |   default: 
45   |     die;
46   |     return -1; /* will never execute */
47   |   }
48   | }
49   | 
50   | /* 
51   |    returns 1 if the given space may appear for a given attribute 
52   | */
53   | int RP_attr2spc(rp_attr_t type, ip_space_t space)
54   | {
55   |   if ( space == IP_V4 ) {
56   |     switch( type ) {
57   |     case  A_DN: 
58   |     case  A_RT:  
59   |     case  A_IN: 
60   |       return 1;
61   |     default:
62   |       /* FALLTHROUGH */ ;
63   |     }
64   |   }
65   |   else if( space == IP_V6 ) {
66   |     switch( type ) {
67   |     case  A_DN: 
68   |     case  A_I6:  
69   |       return 1;
70   |     default: 
71   |       /* FALLTHROUGH */ ;
72   |     }
73   |   }
74   |   else {
75   |     die; /* unknown space */
76   |   }
77   | 
78   |   return 0;
79   | }
80   | 
81   | 
82   | er_ret_t
83   | RP_asc2uni(char       *astr,       /*+ string prefix/range/IP/inaddr +*/
84   | 	   rp_attr_t  attr,
85   | 	   rp_uni_t   *uni)        /* destination pointer */
86   | {
87   |   er_ret_t   conv;
88   |   rx_fam_t   fam_id = RP_attr2fam( attr );
89   |   switch( attr ) {
90   |   case A_IN:
91   |     conv = IP_rang_e2b(&(uni->u.in), astr);
92   |     break;
93   |   case A_RT:
94   |   case A_I6: 
95   |     conv = IP_pref_e2b(&(uni->u.rt), astr);  
96   |     break;
97   |   case A_DN:
98   |     conv = IP_revd_e2b(&(uni->u.rt), astr);
99   |     break;
100  |   default:
101  |     /*    die; / * shouldn't have got here */
102  |     conv = IP_INVARG;
103  |   }
104  | 
105  |   if( conv == IP_OK ) {
106  |     uni->fam = fam_id;
107  |     
108  |     if( fam_id == RX_FAM_RT ) {
109  |       uni->space = IP_pref_b2_space( &(uni->u.rt) );
110  |     } else {  /* RX_FAM_IN */
111  |       uni->space = IP_rang_b2_space( &(uni->u.in) );
112  |     }
113  |   }
114  | 
115  |   return conv;
116  | }
117  | 
118  | 
119  | 
120  | /* Function to fill data for radix tree */
121  | /* returns error if string is not valid, also for reverse domains */
122  | er_ret_t
123  | RP_asc2pack(rp_upd_pack_t *pack, rp_attr_t type, char *string)
124  | {
125  |   er_ret_t err;
126  | 
127  |   pack->type = type;
128  |  
129  |   ER_dbg_va(FAC_RP, ASP_RP_PACK_DET, 
130  | 	    "RP_asc2pack: converted attr %s: %s to pack at %08x",
131  | 	    DF_get_attribute_code(type), string, pack );
132  | 				  
133  |  
134  |   err = RP_asc2uni(string, type, &(pack->uni) );
135  |   
136  |   if( type == A_DN && err == IP_OK) {
137  |     /* Check if it is an in-addr.arpa domain, set domain ptr only then */
138  |     pack->d.domain = string;
139  |   }
140  | 
141  |   return err;
142  | }
143  | 
144  | 
145  | /* construct -K contents 
146  |  *
147  |  * MT-NOTE: returns POITNER TO STATIC MEMORY !!!
148  |  * 
149  |  * ASSUMES ONLY ONE UPDATE THREAD RUNNING.
150  |  */
151  | void rp_make_short(rp_upd_pack_t *pack, char **ptr, int *len) 
152  | {
153  | #define STR_L 2048
154  |   static char buf[STR_L];
155  |   char prefstr[IP_PREFSTR_MAX];
156  |   char rangstr[IP_RANGSTR_MAX];
157  | 
158  |   switch( pack->type ) {
159  |   case A_RT: 
160  |     dieif( IP_pref_b2a( &(pack->uni.u.rt), prefstr, IP_PREFSTR_MAX) != IP_OK );
161  |     snprintf(buf, STR_L, "route:    \t%s\norigin:   \t%s\n", prefstr, pack->d.origin);
162  |     break;
163  |   case A_I6:
164  |     dieif( IP_pref_b2a( &(pack->uni.u.rt), prefstr, IP_PREFSTR_MAX) != IP_OK );
165  |     snprintf(buf, STR_L, "inet6num: \t%s\n", prefstr);
166  |     break;
167  |   case A_IN:
168  |     dieif( IP_rang_b2a( &(pack->uni.u.in), rangstr, IP_RANGSTR_MAX) != IP_OK );
169  |     snprintf(buf, STR_L, "inetnum:  \t%s\n", rangstr);
170  |     break;
171  |   case A_DN:
172  |     snprintf(buf, STR_L, "domain:   \t%s\n", pack->d.domain );
173  |     break;
174  |   default:
175  |     /* FALLTHROUGH */
176  |     ;
177  |   }
178  | 
179  |   *ptr = buf;
180  |   *len = strlen(buf);
181  | }
182  | 
183  | /***************** set the values in rx_*_data thingies ***************/
184  | void RP_pack_set_orig(rp_attr_t  attr, rp_upd_pack_t *pack, char *origin)
185  | {
186  |   pack->d.origin = origin;
187  |   /* ignore attr */
188  | }
189  | 
190  | /* those are just interfacing to 
191  |  * functions to convert to IP binary format and retain raw values 
192  |  */
193  | void RP_pack_set_type(rp_attr_t  attr, rp_upd_pack_t *pack)
194  | {
195  |   pack->type = attr;
196  |   pack->uni.fam = RP_attr2fam( attr );
197  | }
198  | 
199  | void RP_pack_set_pref4(rp_attr_t  attr, char *avalue, rp_upd_pack_t *pack,
200  | 		       unsigned *prefix, unsigned *prefix_length)
201  | {
202  |   IP_pref_a2v4(avalue, &(pack->uni.u.rt), prefix, prefix_length);
203  |   pack->uni.space = IP_V4;
204  |   RP_pack_set_type(attr, pack);
205  | }
206  | 
207  | void RP_pack_set_revd(rp_attr_t  attr, char *avalue, rp_upd_pack_t *pack)
208  | {
209  |   dieif(IP_revd_e2b(&(pack->uni.u.rt), avalue) != IP_OK); /* assuming correctness checked */
210  |   pack->d.domain = avalue;
211  |   pack->uni.space = IP_pref_b2_space( &(pack->uni.u.rt) );
212  |   RP_pack_set_type(attr, pack);
213  | }
214  | 
215  | 
216  | void RP_pack_set_pref6(rp_attr_t  attr, char *avalue, rp_upd_pack_t *pack,
217  | 		       ip_v6word_t *high, ip_v6word_t *low, unsigned *prefix_length)
218  | {
219  |   IP_pref_a2v6(avalue, &(pack->uni.u.rt), high, low, prefix_length);
220  |   pack->uni.space = IP_V6;
221  |   RP_pack_set_type(attr, pack);
222  | }
223  | 
224  | void RP_pack_set_rang(rp_attr_t  attr, char *avalue, rp_upd_pack_t *pack,
225  | 		      unsigned *begin_in, unsigned *end_in)
226  | {
227  |   IP_rang_a2v4(avalue, (ip_range_t *) &(pack->uni.u.in),
228  | 	       begin_in, end_in);
229  |   pack->uni.space = IP_V4;
230  |   RP_pack_set_type(attr, pack);
231  | }
232  | 
233  | 
234  | /***************************************************************************/
235  | 
236  | /***************************************************************************/