Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/networking/udhcp/options.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 2  Line 2 
2  /*  /*
3   * options.c -- DHCP server option packet tools   * options.c -- DHCP server option packet tools
4   * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001   * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
5     *
6     * Licensed under GPLv2, see file LICENSE in this tarball for details.
7   */   */
8    
9  #include "common.h"  #include "common.h"
# Line 46  const struct dhcp_option dhcp_options[] Line 48  const struct dhcp_option dhcp_options[]
48  #if ENABLE_FEATURE_UDHCP_RFC3397  #if ENABLE_FEATURE_UDHCP_RFC3397
49   { OPTION_STR1035 | OPTION_LIST            , 0x77 }, /* search             */   { OPTION_STR1035 | OPTION_LIST            , 0x77 }, /* search             */
50  #endif  #endif
51     { OPTION_STATIC_ROUTES                    , 0x79 }, /* DHCP_STATIC_ROUTES */
52   /* MSIE's "Web Proxy Autodiscovery Protocol" support */   /* MSIE's "Web Proxy Autodiscovery Protocol" support */
53   { OPTION_STRING                           , 0xfc }, /* wpad               */   { OPTION_STRING                           , 0xfc }, /* wpad               */
54    
# Line 54  const struct dhcp_option dhcp_options[] Line 57  const struct dhcp_option dhcp_options[]
57   * with "option XXX YYY" syntax in dhcpd config file. */   * with "option XXX YYY" syntax in dhcpd config file. */
58    
59   { OPTION_U16                              , 0x39 }, /* DHCP_MAX_SIZE      */   { OPTION_U16                              , 0x39 }, /* DHCP_MAX_SIZE      */
60   { } /* zeroed terminating entry */   { 0, 0 } /* zeroed terminating entry */
61  };  };
62    
63  /* Used for converting options from incoming packets to env variables  /* Used for converting options from incoming packets to env variables
# Line 95  const char dhcp_option_strings[] ALIGN1 Line 98  const char dhcp_option_strings[] ALIGN1
98  #if ENABLE_FEATURE_UDHCP_RFC3397  #if ENABLE_FEATURE_UDHCP_RFC3397
99   "search" "\0"   "search" "\0"
100  #endif  #endif
101     "staticroutes" "\0" /* DHCP_STATIC_ROUTES  */
102   /* MSIE's "Web Proxy Autodiscovery Protocol" support */   /* MSIE's "Web Proxy Autodiscovery Protocol" support */
103   "wpad" "\0"   "wpad" "\0"
104   ;   ;
# Line 113  const uint8_t dhcp_option_lengths[] ALIG Line 117  const uint8_t dhcp_option_lengths[] ALIG
117   [OPTION_U16] =     2,   [OPTION_U16] =     2,
118   [OPTION_S16] =     2,   [OPTION_S16] =     2,
119   [OPTION_U32] =     4,   [OPTION_U32] =     4,
120   [OPTION_S32] =     4   [OPTION_S32] =     4,
121     /* Just like OPTION_STRING, we use minimum length here */
122     [OPTION_STATIC_ROUTES] = 5,
123  };  };
124    
125    
126  /* get an option with bounds checking (warning, not aligned). */  #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
127  uint8_t* FAST_FUNC get_option(struct dhcpMessage *packet, int code)  static void log_option(const char *pfx, const uint8_t *opt)
128    {
129     if (dhcp_verbose >= 2) {
130     char buf[256 * 2 + 2];
131     *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0';
132     bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf);
133     }
134    }
135    #else
136    # define log_option(pfx, opt) ((void)0)
137    #endif
138    
139    
140    /* get an option with bounds checking (warning, result is not aligned). */
141    uint8_t* FAST_FUNC get_option(struct dhcp_packet *packet, int code)
142  {  {
  int i, length;  
143   uint8_t *optionptr;   uint8_t *optionptr;
144   int over = 0;   int len;
145   int curr = OPTION_FIELD;   int rem;
146     int overload = 0;
147     enum {
148     FILE_FIELD101  = FILE_FIELD  * 0x101,
149     SNAME_FIELD101 = SNAME_FIELD * 0x101,
150     };
151    
152     /* option bytes: [code][len][data1][data2]..[dataLEN] */
153   optionptr = packet->options;   optionptr = packet->options;
154   i = 0;   rem = sizeof(packet->options);
  length = sizeof(packet->options);  
155   while (1) {   while (1) {
156   if (i >= length) {   if (rem <= 0) {
157   bb_error_msg("bogus packet, option fields too long");   bb_error_msg("bogus packet, malformed option field");
158   return NULL;   return NULL;
159   }   }
160   if (optionptr[i + OPT_CODE] == code) {   if (optionptr[OPT_CODE] == DHCP_PADDING) {
161   if (i + 1 + optionptr[i + OPT_LEN] >= length) {   rem--;
162   bb_error_msg("bogus packet, option fields too long");   optionptr++;
163   return NULL;   continue;
  }  
  return optionptr + i + 2;  
164   }   }
165   switch (optionptr[i + OPT_CODE]) {   if (optionptr[OPT_CODE] == DHCP_END) {
166   case DHCP_PADDING:   if ((overload & FILE_FIELD101) == FILE_FIELD) {
167   i++;   /* can use packet->file, and didn't look at it yet */
168   break;   overload |= FILE_FIELD101; /* "we looked at it" */
  case DHCP_OPTION_OVER:  
  if (i + 1 + optionptr[i + OPT_LEN] >= length) {  
  bb_error_msg("bogus packet, option fields too long");  
  return NULL;  
  }  
  over = optionptr[i + 3];  
  i += optionptr[OPT_LEN] + 2;  
  break;  
  case DHCP_END:  
  if (curr == OPTION_FIELD && (over & FILE_FIELD)) {  
169   optionptr = packet->file;   optionptr = packet->file;
170   i = 0;   rem = sizeof(packet->file);
171   length = sizeof(packet->file);   continue;
172   curr = FILE_FIELD;   }
173   } else if (curr == FILE_FIELD && (over & SNAME_FIELD)) {   if ((overload & SNAME_FIELD101) == SNAME_FIELD) {
174     /* can use packet->sname, and didn't look at it yet */
175     overload |= SNAME_FIELD101; /* "we looked at it" */
176   optionptr = packet->sname;   optionptr = packet->sname;
177   i = 0;   rem = sizeof(packet->sname);
178   length = sizeof(packet->sname);   continue;
179   curr = SNAME_FIELD;   }
  } else  
  return NULL;  
180   break;   break;
  default:  
  i += optionptr[OPT_LEN + i] + 2;  
181   }   }
182     len = 2 + optionptr[OPT_LEN];
183     rem -= len;
184     if (rem < 0)
185     continue; /* complain and return NULL */
186    
187     if (optionptr[OPT_CODE] == code) {
188     log_option("Option found", optionptr);
189     return optionptr + OPT_DATA;
190     }
191    
192     if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) {
193     overload |= optionptr[OPT_DATA];
194     /* fall through */
195     }
196     optionptr += len;
197   }   }
198    
199     /* log3 because udhcpc uses it a lot - very noisy */
200     log3("Option 0x%02x not found", code);
201   return NULL;   return NULL;
202  }  }
203    
# Line 180  int FAST_FUNC end_option(uint8_t *option Line 208  int FAST_FUNC end_option(uint8_t *option
208   int i = 0;   int i = 0;
209    
210   while (optionptr[i] != DHCP_END) {   while (optionptr[i] != DHCP_END) {
211   if (optionptr[i] == DHCP_PADDING)   if (optionptr[i] != DHCP_PADDING)
212   i++;   i += optionptr[i + OPT_LEN] + 1;
213   else   i++;
  i += optionptr[i + OPT_LEN] + 2;  
214   }   }
215   return i;   return i;
216  }  }
217    
218    
219  /* add an option string to the options (an option string contains an option code,  /* add an option string to the options */
220   * length, then data) */  /* option bytes: [code][len][data1][data2]..[dataLEN] */
221  int FAST_FUNC add_option_string(uint8_t *optionptr, uint8_t *string)  int FAST_FUNC add_option_string(uint8_t *optionptr, uint8_t *string)
222  {  {
223   int end = end_option(optionptr);   int end = end_option(optionptr);
# Line 201  int FAST_FUNC add_option_string(uint8_t Line 228  int FAST_FUNC add_option_string(uint8_t
228   string[OPT_CODE]);   string[OPT_CODE]);
229   return 0;   return 0;
230   }   }
231   DEBUG("adding option 0x%02x", string[OPT_CODE]);   log_option("Adding option", string);
232   memcpy(optionptr + end, string, string[OPT_LEN] + 2);   memcpy(optionptr + end, string, string[OPT_LEN] + 2);
233   optionptr[end + string[OPT_LEN] + 2] = DHCP_END;   optionptr[end + string[OPT_LEN] + 2] = DHCP_END;
234   return string[OPT_LEN] + 2;   return string[OPT_LEN] + 2;
# Line 222  int FAST_FUNC add_simple_option(uint8_t Line 249  int FAST_FUNC add_simple_option(uint8_t
249   option[OPT_LEN] = len;   option[OPT_LEN] = len;
250   if (BB_BIG_ENDIAN)   if (BB_BIG_ENDIAN)
251   data <<= 8 * (4 - len);   data <<= 8 * (4 - len);
252   /* This memcpy is for processors which can't   /* Assignment is unaligned! */
253   * handle a simple unaligned 32-bit assignment */   move_to_unaligned32(&option[OPT_DATA], data);
  memcpy(&option[OPT_DATA], &data, 4);  
254   return add_option_string(optionptr, option);   return add_option_string(optionptr, option);
255   }   }
256   }   }
257    
258   bb_error_msg("cannot add option 0x%02x", code);   bb_error_msg("can't add option 0x%02x", code);
259   return 0;   return 0;
260  }  }

Legend:
Removed from v.983  
changed lines
  Added in v.984