1 /* 2 * Copyright (C) 2007 Michael Brown <mbrown (at) fensystems.co.uk>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <stdint.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <errno.h> 25 #include <gpxe/in.h> 26 #include <gpxe/xfer.h> 27 #include <gpxe/open.h> 28 #include <gpxe/process.h> 29 #include <gpxe/resolv.h> 30 31 /** @file 32 * 33 * Name resolution 34 * 35 */ 36 37 /*************************************************************************** 38 * 39 * Name resolution interfaces 40 * 41 *************************************************************************** 42 */ 43 44 /** 45 * Name resolution completed 46 * 47 * @v resolv Name resolution interface 48 * @v sa Completed socket address (if successful) 49 * @v rc Final status code 50 */ 51 void resolv_done ( struct resolv_interface *resolv, struct sockaddr *sa, 52 int rc ) { 53 struct resolv_interface *dest = resolv_get_dest ( resolv ); 54 55 resolv_unplug ( resolv ); 56 dest->op->done ( dest, sa, rc ); 57 resolv_put ( dest ); 58 } 59 60 /** 61 * Ignore name resolution done() event 62 * 63 * @v resolv Name resolution interface 64 * @v sa Completed socket address (if successful) 65 * @v rc Final status code 66 */ 67 void ignore_resolv_done ( struct resolv_interface *resolv __unused, 68 struct sockaddr *sa __unused, int rc __unused ) { 69 /* Do nothing */ 70 } 71 72 /** Null name resolution interface operations */ 73 struct resolv_interface_operations null_resolv_ops = { 74 .done = ignore_resolv_done, 75 }; 76 77 /** Null name resolution interface */ 78 struct resolv_interface null_resolv = { 79 .intf = { 80 .dest = &null_resolv.intf, 81 .refcnt = NULL, 82 }, 83 .op = &null_resolv_ops, 84 }; 85 86 /*************************************************************************** 87 * 88 * Numeric name resolver 89 * 90 *************************************************************************** 91 */ 92 93 /** A numeric name resolver */ 94 struct numeric_resolv { 95 /** Reference counter */ 96 struct refcnt refcnt; 97 /** Name resolution interface */ 98 struct resolv_interface resolv; 99 /** Process */ 100 struct process process; 101 /** Completed socket address */ 102 struct sockaddr sa; 103 /** Overall status code */ 104 int rc; 105 }; 106 107 static void numeric_step ( struct process *process ) { 108 struct numeric_resolv *numeric = 109 container_of ( process, struct numeric_resolv, process ); 110 111 resolv_done ( &numeric->resolv, &numeric->sa, numeric->rc ); 112 process_del ( process ); 113 } 114 115 static int numeric_resolv ( struct resolv_interface *resolv, 116 const char *name, struct sockaddr *sa ) { 117 struct numeric_resolv *numeric; 118 struct sockaddr_in *sin; 119 120 /* Allocate and initialise structure */ 121 numeric = zalloc ( sizeof ( *numeric ) ); 122 if ( ! numeric ) 123 return -ENOMEM; 124 resolv_init ( &numeric->resolv, &null_resolv_ops, &numeric->refcnt ); 125 process_init ( &numeric->process, numeric_step, &numeric->refcnt ); 126 memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) ); 127 128 DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n", 129 numeric, name ); 130 131 /* Attempt to resolve name */ 132 sin = ( ( struct sockaddr_in * ) &numeric->sa ); 133 sin->sin_family = AF_INET; 134 if ( inet_aton ( name, &sin->sin_addr ) == 0 ) 135 numeric->rc = -EINVAL; 136 137 /* Attach to parent interface, mortalise self, and return */ 138 resolv_plug_plug ( &numeric->resolv, resolv ); 139 ref_put ( &numeric->refcnt ); 140 return 0; 141 } 142 143 struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = { 144 .name = "NUMERIC", 145 .resolv = numeric_resolv, 146 }; 147 148 /*************************************************************************** 149 * 150 * Name resolution multiplexer 151 * 152 *************************************************************************** 153 */ 154 155 /** A name resolution multiplexer */ 156 struct resolv_mux { 157 /** Reference counter */ 158 struct refcnt refcnt; 159 /** Parent name resolution interface */ 160 struct resolv_interface parent; 161 162 /** Child name resolution interface */ 163 struct resolv_interface child; 164 /** Current child resolver */ 165 struct resolver *resolver; 166 167 /** Socket address to complete */ 168 struct sockaddr sa; 169 /** Name to be resolved 170 * 171 * Must be at end of structure 172 */ 173 char name[0]; 174 }; 175 176 /** 177 * Try current child name resolver 178 * 179 * @v mux Name resolution multiplexer 180 * @ret rc Return status code 181 */ 182 static int resolv_mux_try ( struct resolv_mux *mux ) { 183 struct resolver *resolver = mux->resolver; 184 int rc; 185 186 DBGC ( mux, "RESOLV %p trying method %s\n", mux, resolver->name ); 187 188 if ( ( rc = resolver->resolv ( &mux->child, mux->name, 189 &mux->sa ) ) != 0 ) { 190 DBGC ( mux, "RESOLV %p could not use method %s: %s\n", 191 mux, resolver->name, strerror ( rc ) ); 192 return rc; 193 } 194 195 return 0; 196 } 197 198 /** 199 * Handle done() event from child name resolver 200 * 201 * @v resolv Child name resolution interface 202 * @v sa Completed socket address (if successful) 203 * @v rc Final status code 204 */ 205 static void resolv_mux_done ( struct resolv_interface *resolv, 206 struct sockaddr *sa, int rc ) { 207 struct resolv_mux *mux = 208 container_of ( resolv, struct resolv_mux, child ); 209 210 /* Unplug child */ 211 resolv_unplug ( &mux->child ); 212 213 /* If this resolution succeeded, stop now */ 214 if ( rc == 0 ) { 215 DBGC ( mux, "RESOLV %p succeeded using method %s\n", 216 mux, mux->resolver->name ); 217 goto finished; 218 } 219 220 /* Attempt next child resolver, if possible */ 221 mux->resolver++; 222 if ( mux->resolver >= table_end ( RESOLVERS ) ) { 223 DBGC ( mux, "RESOLV %p failed to resolve name\n", mux ); 224 goto finished; 225 } 226 if ( ( rc = resolv_mux_try ( mux ) ) != 0 ) 227 goto finished; 228 229 /* Next resolver is now running */ 230 return; 231 232 finished: 233 resolv_done ( &mux->parent, sa, rc ); 234 } 235 236 /** Name resolution multiplexer operations */ 237 static struct resolv_interface_operations resolv_mux_child_ops = { 238 .done = resolv_mux_done, 239 }; 240 241 /** 242 * Start name resolution 243 * 244 * @v resolv Name resolution interface 245 * @v name Name to resolve 246 * @v sa Socket address to complete 247 * @ret rc Return status code 248 */ 249 int resolv ( struct resolv_interface *resolv, const char *name, 250 struct sockaddr *sa ) { 251 struct resolv_mux *mux; 252 size_t name_len = ( strlen ( name ) + 1 ); 253 int rc; 254 255 /* Allocate and initialise structure */ 256 mux = zalloc ( sizeof ( *mux ) + name_len ); 257 if ( ! mux ) 258 return -ENOMEM; 259 resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt ); 260 resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt ); 261 mux->resolver = table_start ( RESOLVERS ); 262 memcpy ( &mux->sa, sa, sizeof ( mux->sa ) ); 263 memcpy ( mux->name, name, name_len ); 264 265 DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name ); 266 267 /* Start first resolver in chain. There will always be at 268 * least one resolver (the numeric resolver), so no need to 269 * check for the zero-resolvers-available case. 270 */ 271 if ( ( rc = resolv_mux_try ( mux ) ) != 0 ) 272 goto err; 273 274 /* Attach parent interface, mortalise self, and return */ 275 resolv_plug_plug ( &mux->parent, resolv ); 276 ref_put ( &mux->refcnt ); 277 return 0; 278 279 err: 280 ref_put ( &mux->refcnt ); 281 return rc; 282 } 283 284 /*************************************************************************** 285 * 286 * Named socket opening 287 * 288 *************************************************************************** 289 */ 290 291 /** A named socket */ 292 struct named_socket { 293 /** Reference counter */ 294 struct refcnt refcnt; 295 /** Data transfer interface */ 296 struct xfer_interface xfer; 297 /** Name resolution interface */ 298 struct resolv_interface resolv; 299 /** Communication semantics (e.g. SOCK_STREAM) */ 300 int semantics; 301 /** Stored local socket address, if applicable */ 302 struct sockaddr local; 303 /** Stored local socket address exists */ 304 int have_local; 305 }; 306 307 /** 308 * Finish using named socket 309 * 310 * @v named Named socket 311 * @v rc Reason for finish 312 */ 313 static void named_done ( struct named_socket *named, int rc ) { 314 315 /* Close all interfaces */ 316 resolv_nullify ( &named->resolv ); 317 xfer_nullify ( &named->xfer ); 318 xfer_close ( &named->xfer, rc ); 319 } 320 321 /** 322 * Handle close() event 323 * 324 * @v xfer Data transfer interface 325 * @v rc Reason for close 326 */ 327 static void named_xfer_close ( struct xfer_interface *xfer, int rc ) { 328 struct named_socket *named = 329 container_of ( xfer, struct named_socket, xfer ); 330 331 named_done ( named, rc ); 332 } 333 334 /** Named socket opener data transfer interface operations */ 335 static struct xfer_interface_operations named_xfer_ops = { 336 .close = named_xfer_close, 337 .vredirect = ignore_xfer_vredirect, 338 .window = no_xfer_window, 339 .alloc_iob = default_xfer_alloc_iob, 340 .deliver_iob = xfer_deliver_as_raw, 341 .deliver_raw = ignore_xfer_deliver_raw, 342 }; 343 344 /** 345 * Handle done() event 346 * 347 * @v resolv Name resolution interface 348 * @v sa Completed socket address (if successful) 349 * @v rc Final status code 350 */ 351 static void named_resolv_done ( struct resolv_interface *resolv, 352 struct sockaddr *sa, int rc ) { 353 struct named_socket *named = 354 container_of ( resolv, struct named_socket, resolv ); 355 356 /* Redirect if name resolution was successful */ 357 if ( rc == 0 ) { 358 rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET, 359 named->semantics, sa, 360 ( named->have_local ? 361 &named->local : NULL ) ); 362 } 363 364 /* Terminate resolution */ 365 named_done ( named, rc ); 366 } 367 368 /** Named socket opener name resolution interface operations */ 369 static struct resolv_interface_operations named_resolv_ops = { 370 .done = named_resolv_done, 371 }; 372 373 /** 374 * Open named socket 375 * 376 * @v semantics Communication semantics (e.g. SOCK_STREAM) 377 * @v peer Peer socket address to complete 378 * @v name Name to resolve 379 * @v local Local socket address, or NULL 380 * @ret rc Return status code 381 */ 382 int xfer_open_named_socket ( struct xfer_interface *xfer, int semantics, 383 struct sockaddr *peer, const char *name, 384 struct sockaddr *local ) { 385 struct named_socket *named; 386 int rc; 387 388 /* Allocate and initialise structure */ 389 named = zalloc ( sizeof ( *named ) ); 390 if ( ! named ) 391 return -ENOMEM; 392 xfer_init ( &named->xfer, &named_xfer_ops, &named->refcnt ); 393 resolv_init ( &named->resolv, &named_resolv_ops, &named->refcnt ); 394 named->semantics = semantics; 395 if ( local ) { 396 memcpy ( &named->local, local, sizeof ( named->local ) ); 397 named->have_local = 1; 398 } 399 400 DBGC ( named, "RESOLV %p opening named socket \"%s\"\n", 401 named, name ); 402 403 /* Start name resolution */ 404 if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 ) 405 goto err; 406 407 /* Attach parent interface, mortalise self, and return */ 408 xfer_plug_plug ( &named->xfer, xfer ); 409 ref_put ( &named->refcnt ); 410 return 0; 411 412 err: 413 ref_put ( &named->refcnt ); 414 return rc; 415 } 416