| 2282 | | ############################################################################# |
|---|
| 2283 | | ############################################################################# |
|---|
| 2284 | | ### DHCPv6 ### |
|---|
| 2285 | | ############################################################################# |
|---|
| 2286 | | ############################################################################# |
|---|
| 2287 | | |
|---|
| 2288 | | All_DHCP_Relay_Agents_and_Servers = "ff02::1:2" |
|---|
| 2289 | | All_DHCP_Servers = "ff05::1:3" # Site-Local scope : deprecated by 3879 |
|---|
| 2290 | | |
|---|
| 2291 | | dhcp6opts = { 1: "CLIENTID", |
|---|
| 2292 | | 2: "SERVERID", |
|---|
| 2293 | | 3: "IA_NA", |
|---|
| 2294 | | 4: "IA_TA", |
|---|
| 2295 | | 5: "IAADDR", |
|---|
| 2296 | | 6: "ORO", |
|---|
| 2297 | | 7: "PREFERENCE", |
|---|
| 2298 | | 8: "ELAPSED_TIME", |
|---|
| 2299 | | 9: "RELAY_MSG", |
|---|
| 2300 | | 11: "AUTH", |
|---|
| 2301 | | 12: "UNICAST", |
|---|
| 2302 | | 13: "STATUS_CODE", |
|---|
| 2303 | | 14: "RAPID_COMMIT", |
|---|
| 2304 | | 15: "USER_CLASS", |
|---|
| 2305 | | 16: "VENDOR_CLASS", |
|---|
| 2306 | | 17: "VENDOR_OPTS", |
|---|
| 2307 | | 18: "INTERFACE_ID", |
|---|
| 2308 | | 19: "RECONF_MSG", |
|---|
| 2309 | | 20: "RECONF_ACCEPT", |
|---|
| 2310 | | 21: "SIP Servers Domain Name List", #RFC3319 |
|---|
| 2311 | | 22: "SIP Servers IPv6 Address List", #RFC3319 |
|---|
| 2312 | | 23: "DNS Recursive Name Server Option", #RFC3646 |
|---|
| 2313 | | 24: "Domain Search List option", #RFC3646 |
|---|
| 2314 | | 25: "OPTION_IA_PD", #RFC3633 |
|---|
| 2315 | | 26: "OPTION_IAPREFIX", #RFC3633 |
|---|
| 2316 | | 27: "OPTION_NIS_SERVERS", #RFC3898 |
|---|
| 2317 | | 28: "OPTION_NISP_SERVERS", #RFC3898 |
|---|
| 2318 | | 29: "OPTION_NIS_DOMAIN_NAME", #RFC3898 |
|---|
| 2319 | | 30: "OPTION_NISP_DOMAIN_NAME", #RFC3898 |
|---|
| 2320 | | 31: "OPTION_SNTP_SERVERS", #RFC4075 |
|---|
| 2321 | | 32: "OPTION_INFORMATION_REFRESH_TIME", #RFC4242 |
|---|
| 2322 | | 33: "OPTION_BCMCS_SERVER_D", #RFC4280 |
|---|
| 2323 | | 34: "OPTION_BCMCS_SERVER_A", #RFC4280 |
|---|
| 2324 | | 36: "OPTION_GEOCONF_CIVIC", #RFC-ietf-geopriv-dhcp-civil-09.txt |
|---|
| 2325 | | 37: "OPTION_REMOTE_ID", #RFC4649 |
|---|
| 2326 | | 38: "OPTION_SUBSCRIBER_ID", #RFC4580 |
|---|
| 2327 | | 39: "OPTION_CLIENT_FQDN" } #RFC4704 |
|---|
| 2328 | | |
|---|
| 2329 | | dhcp6opts_by_code = { 1: "DHCP6OptClientId", |
|---|
| 2330 | | 2: "DHCP6OptServerId", |
|---|
| 2331 | | 3: "DHCP6OptIA_NA", |
|---|
| 2332 | | 4: "DHCP6OptIA_TA", |
|---|
| 2333 | | 5: "DHCP6OptIAAddress", |
|---|
| 2334 | | 6: "DHCP6OptOptReq", |
|---|
| 2335 | | 7: "DHCP6OptPref", |
|---|
| 2336 | | 8: "DHCP6OptElapsedTime", |
|---|
| 2337 | | 9: "DHCP6OptRelayMsg", |
|---|
| 2338 | | 11: "DHCP6OptAuth", |
|---|
| 2339 | | 12: "DHCP6OptServerUnicast", |
|---|
| 2340 | | 13: "DHCP6OptStatusCode", |
|---|
| 2341 | | 14: "DHCP6OptRapidCommit", |
|---|
| 2342 | | 15: "DHCP6OptUserClass", |
|---|
| 2343 | | 16: "DHCP6OptVendorClass", |
|---|
| 2344 | | 17: "DHCP6OptVendorSpecificInfo", |
|---|
| 2345 | | 18: "DHCP6OptIfaceId", |
|---|
| 2346 | | 19: "DHCP6OptReconfMsg", |
|---|
| 2347 | | 20: "DHCP6OptReconfAccept", |
|---|
| 2348 | | 21: "DHCP6OptSIPDomains", #RFC3319 |
|---|
| 2349 | | 22: "DHCP6OptSIPServers", #RFC3319 |
|---|
| 2350 | | 23: "DHCP6OptDNSServers", #RFC3646 |
|---|
| 2351 | | 24: "DHCP6OptDNSDomains", #RFC3646 |
|---|
| 2352 | | 25: "DHCP6OptIA_PD", #RFC3633 |
|---|
| 2353 | | 26: "DHCP6OptIAPrefix", #RFC3633 |
|---|
| 2354 | | 27: "DHCP6OptNISServers", #RFC3898 |
|---|
| 2355 | | 28: "DHCP6OptNISPServers", #RFC3898 |
|---|
| 2356 | | 29: "DHCP6OptNISDomain", #RFC3898 |
|---|
| 2357 | | 30: "DHCP6OptNISPDomain", #RFC3898 |
|---|
| 2358 | | 31: "DHCP6OptSNTPServers", #RFC4075 |
|---|
| 2359 | | 32: "DHCP6OptInfoRefreshTime", #RFC4242 |
|---|
| 2360 | | 33: "DHCP6OptBCMCSDomains", #RFC4280 |
|---|
| 2361 | | 34: "DHCP6OptBCMCSServers", #RFC4280 |
|---|
| 2362 | | #36: "DHCP6OptGeoConf", #RFC-ietf-geopriv-dhcp-civil-09.txt |
|---|
| 2363 | | 37: "DHCP6OptRemoteID", #RFC4649 |
|---|
| 2364 | | 38: "DHCP6OptSubscriberID", #RFC4580 |
|---|
| 2365 | | 39: "DHCP6OptClientFQDN", #RFC4704 |
|---|
| 2366 | | #40: "DHCP6OptPANAAgent", #RFC-ietf-dhc-paa-option-05.txt |
|---|
| 2367 | | #41: "DHCP6OptNewPOSIXTimeZone, #RFC4833 |
|---|
| 2368 | | #42: "DHCP6OptNewTZDBTimeZone, #RFC4833 |
|---|
| 2369 | | 43: "DHCP6OptRelayAgentERO" #RFC4994 |
|---|
| 2370 | | #44: "DHCP6OptLQQuery", #RFC5007 |
|---|
| 2371 | | #45: "DHCP6OptLQClientData", #RFC5007 |
|---|
| 2372 | | #46: "DHCP6OptLQClientTime", #RFC5007 |
|---|
| 2373 | | #47: "DHCP6OptLQRelayData", #RFC5007 |
|---|
| 2374 | | #48: "DHCP6OptLQClientLink", #RFC5007 |
|---|
| 2375 | | } |
|---|
| 2376 | | |
|---|
| 2377 | | |
|---|
| 2378 | | # sect 5.3 RFC 3315 : DHCP6 Messages types |
|---|
| 2379 | | dhcp6types = { 1:"SOLICIT", |
|---|
| 2380 | | 2:"ADVERTISE", |
|---|
| 2381 | | 3:"REQUEST", |
|---|
| 2382 | | 4:"CONFIRM", |
|---|
| 2383 | | 5:"RENEW", |
|---|
| 2384 | | 6:"REBIND", |
|---|
| 2385 | | 7:"REPLY", |
|---|
| 2386 | | 8:"RELEASE", |
|---|
| 2387 | | 9:"DECLINE", |
|---|
| 2388 | | 10:"RECONFIGURE", |
|---|
| 2389 | | 11:"INFORMATION-REQUEST", |
|---|
| 2390 | | 12:"RELAY-FORW", |
|---|
| 2391 | | 13:"RELAY-REPL" } |
|---|
| 2392 | | |
|---|
| 2393 | | |
|---|
| 2394 | | ##################################################################### |
|---|
| 2395 | | ### DHCPv6 DUID related stuff ### |
|---|
| 2396 | | ##################################################################### |
|---|
| 2397 | | |
|---|
| 2398 | | duidtypes = { 1: "Link-layer address plus time", |
|---|
| 2399 | | 2: "Vendor-assigned unique ID based on Enterprise Number", |
|---|
| 2400 | | 3: "Link-layer Address" } |
|---|
| 2401 | | |
|---|
| 2402 | | # DUID hardware types - RFC 826 - Extracted from |
|---|
| 2403 | | # http://www.iana.org/assignments/arp-parameters on 31/10/06 |
|---|
| 2404 | | # We should add the length of every kind of address. |
|---|
| 2405 | | duidhwtypes = { 0: "NET/ROM pseudo", # Not referenced by IANA |
|---|
| 2406 | | 1: "Ethernet (10Mb)", |
|---|
| 2407 | | 2: "Experimental Ethernet (3Mb)", |
|---|
| 2408 | | 3: "Amateur Radio AX.25", |
|---|
| 2409 | | 4: "Proteon ProNET Token Ring", |
|---|
| 2410 | | 5: "Chaos", |
|---|
| 2411 | | 6: "IEEE 802 Networks", |
|---|
| 2412 | | 7: "ARCNET", |
|---|
| 2413 | | 8: "Hyperchannel", |
|---|
| 2414 | | 9: "Lanstar", |
|---|
| 2415 | | 10: "Autonet Short Address", |
|---|
| 2416 | | 11: "LocalTalk", |
|---|
| 2417 | | 12: "LocalNet (IBM PCNet or SYTEK LocalNET)", |
|---|
| 2418 | | 13: "Ultra link", |
|---|
| 2419 | | 14: "SMDS", |
|---|
| 2420 | | 15: "Frame Relay", |
|---|
| 2421 | | 16: "Asynchronous Transmission Mode (ATM)", |
|---|
| 2422 | | 17: "HDLC", |
|---|
| 2423 | | 18: "Fibre Channel", |
|---|
| 2424 | | 19: "Asynchronous Transmission Mode (ATM)", |
|---|
| 2425 | | 20: "Serial Line", |
|---|
| 2426 | | 21: "Asynchronous Transmission Mode (ATM)", |
|---|
| 2427 | | 22: "MIL-STD-188-220", |
|---|
| 2428 | | 23: "Metricom", |
|---|
| 2429 | | 24: "IEEE 1394.1995", |
|---|
| 2430 | | 25: "MAPOS", |
|---|
| 2431 | | 26: "Twinaxial", |
|---|
| 2432 | | 27: "EUI-64", |
|---|
| 2433 | | 28: "HIPARP", |
|---|
| 2434 | | 29: "IP and ARP over ISO 7816-3", |
|---|
| 2435 | | 30: "ARPSec", |
|---|
| 2436 | | 31: "IPsec tunnel", |
|---|
| 2437 | | 32: "InfiniBand (TM)", |
|---|
| 2438 | | 33: "TIA-102 Project 25 Common Air Interface (CAI)" } |
|---|
| 2439 | | |
|---|
| 2440 | | class UTCTimeField(IntField): |
|---|
| 2441 | | epoch = (2000, 1, 1, 0, 0, 0, 5, 1, 0) # required Epoch |
|---|
| 2442 | | def i2repr(self, pkt, x): |
|---|
| 2443 | | x = self.i2h(pkt, x) |
|---|
| 2444 | | from time import gmtime, strftime, mktime |
|---|
| 2445 | | delta = mktime(self.epoch) - mktime(gmtime(0)) |
|---|
| 2446 | | x = x + delta |
|---|
| 2447 | | t = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(x)) |
|---|
| 2448 | | return "%s (%d)" % (t, x) |
|---|
| 2449 | | |
|---|
| 2450 | | class _LLAddrField(MACField): |
|---|
| 2451 | | pass |
|---|
| 2452 | | |
|---|
| 2453 | | # XXX We only support Ethernet addresses at the moment. _LLAddrField |
|---|
| 2454 | | # will be modified when needed. Ask us. --arno |
|---|
| 2455 | | class DUID_LLT(Packet): # sect 9.2 RFC 3315 |
|---|
| 2456 | | name = "DUID - Link-layer address plus time" |
|---|
| 2457 | | fields_desc = [ ShortEnumField("type", 1, duidtypes), |
|---|
| 2458 | | XShortEnumField("hwtype", 1, duidhwtypes), |
|---|
| 2459 | | UTCTimeField("timeval", 0), # i.e. 01 Jan 2000 |
|---|
| 2460 | | _LLAddrField("lladdr", ETHER_ANY) ] |
|---|
| 2461 | | |
|---|
| 2462 | | # In fact, IANA enterprise-numbers file available at |
|---|
| 2463 | | # http//www.iana.org/asignments/enterprise-numbers) |
|---|
| 2464 | | # is simply huge (more than 2Mo and 600Ko in bz2). I'll |
|---|
| 2465 | | # add only most common vendors, and encountered values. |
|---|
| 2466 | | # -- arno |
|---|
| 2467 | | iana_enterprise_num = { 9: "ciscoSystems", |
|---|
| 2468 | | 35: "Nortel Networks", |
|---|
| 2469 | | 43: "3Com", |
|---|
| 2470 | | 311: "Microsoft", |
|---|
| 2471 | | 2636: "Juniper Networks, Inc.", |
|---|
| 2472 | | 4526: "Netgear", |
|---|
| 2473 | | 5771: "Cisco Systems, Inc.", |
|---|
| 2474 | | 5842: "Cisco Systems", |
|---|
| 2475 | | 16885: "Nortel Networks" } |
|---|
| 2476 | | |
|---|
| 2477 | | class DUID_EN(Packet): # sect 9.3 RFC 3315 |
|---|
| 2478 | | name = "DUID - Assigned by Vendor Based on Enterprise Number" |
|---|
| 2479 | | fields_desc = [ ShortEnumField("type", 2, duidtypes), |
|---|
| 2480 | | IntEnumField("enterprisenum", 311, iana_enterprise_num), |
|---|
| 2481 | | StrField("id","") ] |
|---|
| 2482 | | |
|---|
| 2483 | | class DUID_LL(Packet): # sect 9.4 RFC 3315 |
|---|
| 2484 | | name = "DUID - Based on Link-layer Address" |
|---|
| 2485 | | fields_desc = [ ShortEnumField("type", 3, duidtypes), |
|---|
| 2486 | | XShortEnumField("hwtype", 1, duidhwtypes), |
|---|
| 2487 | | _LLAddrField("lladdr", ETHER_ANY) ] |
|---|
| 2488 | | |
|---|
| 2489 | | duid_cls = { 1: "DUID_LLT", |
|---|
| 2490 | | 2: "DUID_EN", |
|---|
| 2491 | | 3: "DUID_LL"} |
|---|
| 2492 | | |
|---|
| 2493 | | ##################################################################### |
|---|
| 2494 | | ### DHCPv6 Options classes ### |
|---|
| 2495 | | ##################################################################### |
|---|
| 2496 | | |
|---|
| 2497 | | class _DHCP6OptGuessPayload(Packet): |
|---|
| 2498 | | def guess_payload_class(self, payload): |
|---|
| 2499 | | cls = Raw |
|---|
| 2500 | | if len(payload) > 2 : |
|---|
| 2501 | | opt = struct.unpack("!H", payload[:2])[0] |
|---|
| 2502 | | cls = get_cls(dhcp6opts_by_code.get(opt, "DHCP6OptUnknown"), DHCP6OptUnknown) |
|---|
| 2503 | | return cls |
|---|
| 2504 | | |
|---|
| 2505 | | class DHCP6OptUnknown(_DHCP6OptGuessPayload): # A generic DHCPv6 Option |
|---|
| 2506 | | name = "Unknown DHCPv6 OPtion" |
|---|
| 2507 | | fields_desc = [ ShortEnumField("optcode", 0, dhcp6opts), |
|---|
| 2508 | | FieldLenField("optlen", None, length_of="data", fmt="!H"), |
|---|
| 2509 | | StrLenField("data", "", |
|---|
| 2510 | | length_from = lambda pkt: pkt.optlen)] |
|---|
| 2511 | | |
|---|
| 2512 | | class _DUIDField(PacketField): |
|---|
| 2513 | | holds_packets=1 |
|---|
| 2514 | | def __init__(self, name, default, length_from=None): |
|---|
| 2515 | | StrField.__init__(self, name, default) |
|---|
| 2516 | | self.length_from = length_from |
|---|
| 2517 | | |
|---|
| 2518 | | def i2m(self, pkt, i): |
|---|
| 2519 | | return str(i) |
|---|
| 2520 | | |
|---|
| 2521 | | def m2i(self, pkt, x): |
|---|
| 2522 | | cls = Raw |
|---|
| 2523 | | if len(x) > 4: |
|---|
| 2524 | | o = struct.unpack("!H", x[:2])[0] |
|---|
| 2525 | | cls = get_cls(duid_cls.get(o, Raw), "Raw") |
|---|
| 2526 | | return cls(x) |
|---|
| 2527 | | |
|---|
| 2528 | | def getfield(self, pkt, s): |
|---|
| 2529 | | l = self.length_from(pkt) |
|---|
| 2530 | | return s[l:], self.m2i(pkt,s[:l]) |
|---|
| 2531 | | |
|---|
| 2532 | | |
|---|
| 2533 | | class DHCP6OptClientId(_DHCP6OptGuessPayload): # RFC sect 22.2 |
|---|
| 2534 | | name = "DHCP6 Client Identifier Option" |
|---|
| 2535 | | fields_desc = [ ShortEnumField("optcode", 1, dhcp6opts), |
|---|
| 2536 | | FieldLenField("optlen", None, length_of="duid", fmt="!H"), |
|---|
| 2537 | | _DUIDField("duid", "", |
|---|
| 2538 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2539 | | |
|---|
| 2540 | | |
|---|
| 2541 | | class DHCP6OptServerId(DHCP6OptClientId): # RFC sect 22.3 |
|---|
| 2542 | | name = "DHCP6 Server Identifier Option" |
|---|
| 2543 | | __metaclass__ = NewDefaultValues |
|---|
| 2544 | | optcode = 2 |
|---|
| 2545 | | |
|---|
| 2546 | | # Should be encapsulated in the option field of IA_NA or IA_TA options |
|---|
| 2547 | | # Can only appear at that location. |
|---|
| 2548 | | # TODO : last field IAaddr-options is not defined in the reference document |
|---|
| 2549 | | class DHCP6OptIAAddress(_DHCP6OptGuessPayload): # RFC sect 22.6 |
|---|
| 2550 | | name = "DHCP6 IA Address Option (IA_TA or IA_NA suboption)" |
|---|
| 2551 | | fields_desc = [ ShortEnumField("optcode", 5, dhcp6opts), |
|---|
| 2552 | | FieldLenField("optlen", None, length_of="iaaddropts", |
|---|
| 2553 | | fmt="!H", adjust = lambda pkt,x: x+24), |
|---|
| 2554 | | IP6Field("addr", "::"), |
|---|
| 2555 | | IntField("preflft", 0), |
|---|
| 2556 | | IntField("validlft", 0), |
|---|
| 2557 | | XIntField("iaid", None), |
|---|
| 2558 | | StrLenField("iaaddropts", "", |
|---|
| 2559 | | length_from = lambda pkt: pkt.optlen - 24) ] |
|---|
| 2560 | | def guess_payload_class(self, payload): |
|---|
| 2561 | | return Padding |
|---|
| 2562 | | |
|---|
| 2563 | | class _IANAOptField(PacketListField): |
|---|
| 2564 | | def i2len(self, pkt, z): |
|---|
| 2565 | | if z is None or z == []: |
|---|
| 2566 | | return 0 |
|---|
| 2567 | | return sum(map(lambda x: len(str(x)) ,z)) |
|---|
| 2568 | | |
|---|
| 2569 | | def getfield(self, pkt, s): |
|---|
| 2570 | | l = self.length_from(pkt) |
|---|
| 2571 | | lst = [] |
|---|
| 2572 | | remain, payl = s[:l], s[l:] |
|---|
| 2573 | | while len(remain)>0: |
|---|
| 2574 | | p = self.m2i(pkt,remain) |
|---|
| 2575 | | if Padding in p: |
|---|
| 2576 | | pad = p[Padding] |
|---|
| 2577 | | remain = pad.load |
|---|
| 2578 | | del(pad.underlayer.payload) |
|---|
| 2579 | | else: |
|---|
| 2580 | | remain = "" |
|---|
| 2581 | | lst.append(p) |
|---|
| 2582 | | return payl,lst |
|---|
| 2583 | | |
|---|
| 2584 | | class DHCP6OptIA_NA(_DHCP6OptGuessPayload): # RFC sect 22.4 |
|---|
| 2585 | | name = "DHCP6 Identity Association for Non-temporary Addresses Option" |
|---|
| 2586 | | fields_desc = [ ShortEnumField("optcode", 3, dhcp6opts), |
|---|
| 2587 | | FieldLenField("optlen", None, length_of="ianaopts", |
|---|
| 2588 | | fmt="!H", adjust = lambda pkt,x: x+12), |
|---|
| 2589 | | XIntField("iaid", None), |
|---|
| 2590 | | IntField("T1", None), |
|---|
| 2591 | | IntField("T2", None), |
|---|
| 2592 | | _IANAOptField("ianaopts", [], DHCP6OptIAAddress, |
|---|
| 2593 | | length_from = lambda pkt: pkt.optlen-12) ] |
|---|
| 2594 | | |
|---|
| 2595 | | class _IATAOptField(_IANAOptField): |
|---|
| 2596 | | pass |
|---|
| 2597 | | |
|---|
| 2598 | | class DHCP6OptIA_TA(_DHCP6OptGuessPayload): # RFC sect 22.5 |
|---|
| 2599 | | name = "DHCP6 Identity Association for Temporary Addresses Option" |
|---|
| 2600 | | fields_desc = [ ShortEnumField("optcode", 4, dhcp6opts), |
|---|
| 2601 | | FieldLenField("optlen", None, length_of="iataopts", |
|---|
| 2602 | | fmt="!H", adjust = lambda pkt,x: x+4), |
|---|
| 2603 | | XIntField("iaid", None), |
|---|
| 2604 | | _IATAOptField("iataopts", [], DHCP6OptIAAddress, |
|---|
| 2605 | | length_from = lambda pkt: pkt.optlen-4) ] |
|---|
| 2606 | | |
|---|
| 2607 | | |
|---|
| 2608 | | #### DHCPv6 Option Request Option ################################### |
|---|
| 2609 | | |
|---|
| 2610 | | class _OptReqListField(StrLenField): |
|---|
| 2611 | | islist = 1 |
|---|
| 2612 | | def i2h(self, pkt, x): |
|---|
| 2613 | | if x is None: |
|---|
| 2614 | | return [] |
|---|
| 2615 | | return x |
|---|
| 2616 | | |
|---|
| 2617 | | def i2len(self, pkt, x): |
|---|
| 2618 | | return 2*len(x) |
|---|
| 2619 | | |
|---|
| 2620 | | def any2i(self, pkt, x): |
|---|
| 2621 | | return x |
|---|
| 2622 | | |
|---|
| 2623 | | def i2repr(self, pkt, x): |
|---|
| 2624 | | s = [] |
|---|
| 2625 | | for y in self.i2h(pkt, x): |
|---|
| 2626 | | if dhcp6opts.has_key(y): |
|---|
| 2627 | | s.append(dhcp6opts[y]) |
|---|
| 2628 | | else: |
|---|
| 2629 | | s.append("%d" % y) |
|---|
| 2630 | | return "[%s]" % ", ".join(s) |
|---|
| 2631 | | |
|---|
| 2632 | | def m2i(self, pkt, x): |
|---|
| 2633 | | r = [] |
|---|
| 2634 | | while len(x) != 0: |
|---|
| 2635 | | if len(x)<2: |
|---|
| 2636 | | warning("Odd length for requested option field. Rejecting last byte") |
|---|
| 2637 | | return r |
|---|
| 2638 | | r.append(struct.unpack("!H", x[:2])[0]) |
|---|
| 2639 | | x = x[2:] |
|---|
| 2640 | | return r |
|---|
| 2641 | | |
|---|
| 2642 | | def i2m(self, pkt, x): |
|---|
| 2643 | | return "".join(map(lambda y: struct.pack("!H", y), x)) |
|---|
| 2644 | | |
|---|
| 2645 | | # A client may include an ORO in a solicit, Request, Renew, Rebind, |
|---|
| 2646 | | # Confirm or Information-request |
|---|
| 2647 | | class DHCP6OptOptReq(_DHCP6OptGuessPayload): # RFC sect 22.7 |
|---|
| 2648 | | name = "DHCP6 Option Request Option" |
|---|
| 2649 | | fields_desc = [ ShortEnumField("optcode", 6, dhcp6opts), |
|---|
| 2650 | | FieldLenField("optlen", None, length_of="reqopts", fmt="!H"), |
|---|
| 2651 | | _OptReqListField("reqopts", [23, 24], |
|---|
| 2652 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2653 | | |
|---|
| 2654 | | |
|---|
| 2655 | | #### DHCPv6 Preference Option ####################################### |
|---|
| 2656 | | |
|---|
| 2657 | | # emise par un serveur pour affecter le choix fait par le client. Dans |
|---|
| 2658 | | # les messages Advertise, a priori |
|---|
| 2659 | | class DHCP6OptPref(_DHCP6OptGuessPayload): # RFC sect 22.8 |
|---|
| 2660 | | name = "DHCP6 Preference Option" |
|---|
| 2661 | | fields_desc = [ ShortEnumField("optcode", 7, dhcp6opts), |
|---|
| 2662 | | ShortField("optlen", 1 ), |
|---|
| 2663 | | ByteField("prefval",255) ] |
|---|
| 2664 | | |
|---|
| 2665 | | |
|---|
| 2666 | | #### DHCPv6 Elapsed Time Option ##################################### |
|---|
| 2667 | | |
|---|
| 2668 | | class _ElapsedTimeField(ShortField): |
|---|
| 2669 | | def i2repr(self, pkt, x): |
|---|
| 2670 | | if x == 0xffff: |
|---|
| 2671 | | return "infinity (0xffff)" |
|---|
| 2672 | | return "%.2f sec" % (self.i2h(pkt, x)/100.) |
|---|
| 2673 | | |
|---|
| 2674 | | class DHCP6OptElapsedTime(_DHCP6OptGuessPayload):# RFC sect 22.9 |
|---|
| 2675 | | name = "DHCP6 Elapsed Time Option" |
|---|
| 2676 | | fields_desc = [ ShortEnumField("optcode", 8, dhcp6opts), |
|---|
| 2677 | | ShortField("optlen", 2), |
|---|
| 2678 | | _ElapsedTimeField("elapsedtime", 0) ] |
|---|
| 2679 | | |
|---|
| 2680 | | |
|---|
| 2681 | | #### DHCPv6 Relay Message Option #################################### |
|---|
| 2682 | | |
|---|
| 2683 | | # Relayed message is seen as a payload. |
|---|
| 2684 | | class DHCP6OptRelayMsg(_DHCP6OptGuessPayload):# RFC sect 22.10 |
|---|
| 2685 | | name = "DHCP6 Relay Message Option" |
|---|
| 2686 | | fields_desc = [ ShortEnumField("optcode", 9, dhcp6opts), |
|---|
| 2687 | | ShortField("optlen", None ) ] |
|---|
| 2688 | | def post_build(self, p, pay): |
|---|
| 2689 | | if self.optlen is None: |
|---|
| 2690 | | l = len(pay) |
|---|
| 2691 | | p = p[:2]+struct.pack("!H", l) |
|---|
| 2692 | | return p + pay |
|---|
| 2693 | | |
|---|
| 2694 | | |
|---|
| 2695 | | #### DHCPv6 Authentication Option ################################### |
|---|
| 2696 | | |
|---|
| 2697 | | # The following fields are set in an Authentication option for the |
|---|
| 2698 | | # Reconfigure Key Authentication Protocol: |
|---|
| 2699 | | # |
|---|
| 2700 | | # protocol 3 |
|---|
| 2701 | | # |
|---|
| 2702 | | # algorithm 1 |
|---|
| 2703 | | # |
|---|
| 2704 | | # RDM 0 |
|---|
| 2705 | | # |
|---|
| 2706 | | # The format of the Authentication information for the Reconfigure Key |
|---|
| 2707 | | # Authentication Protocol is: |
|---|
| 2708 | | # |
|---|
| 2709 | | # 0 1 2 3 |
|---|
| 2710 | | # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
|---|
| 2711 | | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 2712 | | # | Type | Value (128 bits) | |
|---|
| 2713 | | # +-+-+-+-+-+-+-+-+ | |
|---|
| 2714 | | # . . |
|---|
| 2715 | | # . . |
|---|
| 2716 | | # . +-+-+-+-+-+-+-+-+ |
|---|
| 2717 | | # | | |
|---|
| 2718 | | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 2719 | | # |
|---|
| 2720 | | # Type Type of data in Value field carried in this option: |
|---|
| 2721 | | # |
|---|
| 2722 | | # 1 Reconfigure Key value (used in Reply message). |
|---|
| 2723 | | # |
|---|
| 2724 | | # 2 HMAC-MD5 digest of the message (used in Reconfigure |
|---|
| 2725 | | # message). |
|---|
| 2726 | | # |
|---|
| 2727 | | # Value Data as defined by field. |
|---|
| 2728 | | |
|---|
| 2729 | | |
|---|
| 2730 | | # TODO : Decoding only at the moment |
|---|
| 2731 | | class DHCP6OptAuth(_DHCP6OptGuessPayload): # RFC sect 22.11 |
|---|
| 2732 | | name = "DHCP6 Option - Authentication" |
|---|
| 2733 | | fields_desc = [ ShortEnumField("optcode", 11, dhcp6opts), |
|---|
| 2734 | | FieldLenField("optlen", None, length_of="authinfo", |
|---|
| 2735 | | adjust = lambda pkt,x: x+11), |
|---|
| 2736 | | ByteField("proto", 3), # TODO : XXX |
|---|
| 2737 | | ByteField("alg", 1), # TODO : XXX |
|---|
| 2738 | | ByteField("rdm", 0), # TODO : XXX |
|---|
| 2739 | | StrFixedLenField("replay", "A"*8, 8), # TODO: XXX |
|---|
| 2740 | | StrLenField("authinfo", "", |
|---|
| 2741 | | length_from = lambda pkt: pkt.optlen - 11) ] |
|---|
| 2742 | | |
|---|
| 2743 | | #### DHCPv6 Server Unicast Option ################################### |
|---|
| 2744 | | |
|---|
| 2745 | | class _SrvAddrField(IP6Field): |
|---|
| 2746 | | def i2h(self, pkt, x): |
|---|
| 2747 | | if x is None: |
|---|
| 2748 | | return "::" |
|---|
| 2749 | | return x |
|---|
| 2750 | | |
|---|
| 2751 | | def i2m(self, pkt, x): |
|---|
| 2752 | | return inet_pton(socket.AF_INET6, self.i2h(pkt,x)) |
|---|
| 2753 | | |
|---|
| 2754 | | class DHCP6OptServerUnicast(_DHCP6OptGuessPayload):# RFC sect 22.12 |
|---|
| 2755 | | name = "DHCP6 Server Unicast Option" |
|---|
| 2756 | | fields_desc = [ ShortEnumField("optcode", 12, dhcp6opts), |
|---|
| 2757 | | ShortField("optlen", 16 ), |
|---|
| 2758 | | _SrvAddrField("srvaddr",None) ] |
|---|
| 2759 | | |
|---|
| 2760 | | |
|---|
| 2761 | | #### DHCPv6 Status Code Option ###################################### |
|---|
| 2762 | | |
|---|
| 2763 | | dhcp6statuscodes = { 0:"Success", # sect 24.4 |
|---|
| 2764 | | 1:"UnspecFail", |
|---|
| 2765 | | 2:"NoAddrsAvail", |
|---|
| 2766 | | 3:"NoBinding", |
|---|
| 2767 | | 4:"NotOnLink", |
|---|
| 2768 | | 5:"UseMulticast", |
|---|
| 2769 | | 6:"NoPrefixAvail"} # From RFC3633 |
|---|
| 2770 | | |
|---|
| 2771 | | class DHCP6OptStatusCode(_DHCP6OptGuessPayload):# RFC sect 22.13 |
|---|
| 2772 | | name = "DHCP6 Status Code Option" |
|---|
| 2773 | | fields_desc = [ ShortEnumField("optcode", 13, dhcp6opts), |
|---|
| 2774 | | FieldLenField("optlen", None, length_of="statusmsg", |
|---|
| 2775 | | fmt="!H", adjust = lambda pkt,x:x+2), |
|---|
| 2776 | | ShortEnumField("statuscode",None,dhcp6statuscodes), |
|---|
| 2777 | | StrLenField("statusmsg", "", |
|---|
| 2778 | | length_from = lambda pkt: pkt.optlen-2) ] |
|---|
| 2779 | | |
|---|
| 2780 | | |
|---|
| 2781 | | #### DHCPv6 Rapid Commit Option ##################################### |
|---|
| 2782 | | |
|---|
| 2783 | | class DHCP6OptRapidCommit(_DHCP6OptGuessPayload): # RFC sect 22.14 |
|---|
| 2784 | | name = "DHCP6 Rapid Commit Option" |
|---|
| 2785 | | fields_desc = [ ShortEnumField("optcode", 14, dhcp6opts), |
|---|
| 2786 | | ShortField("optlen", 0)] |
|---|
| 2787 | | |
|---|
| 2788 | | |
|---|
| 2789 | | #### DHCPv6 User Class Option ####################################### |
|---|
| 2790 | | |
|---|
| 2791 | | class _UserClassDataField(PacketListField): |
|---|
| 2792 | | def i2len(self, pkt, z): |
|---|
| 2793 | | if z is None or z == []: |
|---|
| 2794 | | return 0 |
|---|
| 2795 | | return sum(map(lambda x: len(str(x)) ,z)) |
|---|
| 2796 | | |
|---|
| 2797 | | def getfield(self, pkt, s): |
|---|
| 2798 | | l = self.length_from(pkt) |
|---|
| 2799 | | lst = [] |
|---|
| 2800 | | remain, payl = s[:l], s[l:] |
|---|
| 2801 | | while len(remain)>0: |
|---|
| 2802 | | p = self.m2i(pkt,remain) |
|---|
| 2803 | | if Padding in p: |
|---|
| 2804 | | pad = p[Padding] |
|---|
| 2805 | | remain = pad.load |
|---|
| 2806 | | del(pad.underlayer.payload) |
|---|
| 2807 | | else: |
|---|
| 2808 | | remain = "" |
|---|
| 2809 | | lst.append(p) |
|---|
| 2810 | | return payl,lst |
|---|
| 2811 | | |
|---|
| 2812 | | |
|---|
| 2813 | | class USER_CLASS_DATA(Packet): |
|---|
| 2814 | | name = "user class data" |
|---|
| 2815 | | fields_desc = [ FieldLenField("len", None, length_of="data"), |
|---|
| 2816 | | StrLenField("data", "", |
|---|
| 2817 | | length_from = lambda pkt: pkt.len) ] |
|---|
| 2818 | | def guess_payload_class(self, payload): |
|---|
| 2819 | | return Padding |
|---|
| 2820 | | |
|---|
| 2821 | | class DHCP6OptUserClass(_DHCP6OptGuessPayload):# RFC sect 22.15 |
|---|
| 2822 | | name = "DHCP6 User Class Option" |
|---|
| 2823 | | fields_desc = [ ShortEnumField("optcode", 15, dhcp6opts), |
|---|
| 2824 | | FieldLenField("optlen", None, fmt="!H", |
|---|
| 2825 | | length_of="userclassdata"), |
|---|
| 2826 | | _UserClassDataField("userclassdata", [], USER_CLASS_DATA, |
|---|
| 2827 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2828 | | |
|---|
| 2829 | | |
|---|
| 2830 | | #### DHCPv6 Vendor Class Option ##################################### |
|---|
| 2831 | | |
|---|
| 2832 | | class _VendorClassDataField(_UserClassDataField): |
|---|
| 2833 | | pass |
|---|
| 2834 | | |
|---|
| 2835 | | class VENDOR_CLASS_DATA(USER_CLASS_DATA): |
|---|
| 2836 | | name = "vendor class data" |
|---|
| 2837 | | |
|---|
| 2838 | | class DHCP6OptVendorClass(_DHCP6OptGuessPayload):# RFC sect 22.16 |
|---|
| 2839 | | name = "DHCP6 Vendor Class Option" |
|---|
| 2840 | | fields_desc = [ ShortEnumField("optcode", 16, dhcp6opts), |
|---|
| 2841 | | FieldLenField("optlen", None, length_of="vcdata", fmt="!H", |
|---|
| 2842 | | adjust = lambda pkt,x: x+4), |
|---|
| 2843 | | IntEnumField("enterprisenum",None , iana_enterprise_num ), |
|---|
| 2844 | | _VendorClassDataField("vcdata", [], VENDOR_CLASS_DATA, |
|---|
| 2845 | | length_from = lambda pkt: pkt.optlen-4) ] |
|---|
| 2846 | | |
|---|
| 2847 | | #### DHCPv6 Vendor-Specific Information Option ###################### |
|---|
| 2848 | | |
|---|
| 2849 | | class VENDOR_SPECIFIC_OPTION(_DHCP6OptGuessPayload): |
|---|
| 2850 | | name = "vendor specific option data" |
|---|
| 2851 | | fields_desc = [ ShortField("optcode", None), |
|---|
| 2852 | | FieldLenField("optlen", None, length_of="optdata"), |
|---|
| 2853 | | StrLenField("optdata", "", |
|---|
| 2854 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2855 | | def guess_payload_class(self, payload): |
|---|
| 2856 | | return Padding |
|---|
| 2857 | | |
|---|
| 2858 | | # The third one that will be used for nothing interesting |
|---|
| 2859 | | class DHCP6OptVendorSpecificInfo(_DHCP6OptGuessPayload):# RFC sect 22.17 |
|---|
| 2860 | | name = "DHCP6 Vendor-specific Information Option" |
|---|
| 2861 | | fields_desc = [ ShortEnumField("optcode", 17, dhcp6opts), |
|---|
| 2862 | | FieldLenField("optlen", None, length_of="vso", fmt="!H", |
|---|
| 2863 | | adjust = lambda pkt,x: x+4), |
|---|
| 2864 | | IntEnumField("enterprisenum",None , iana_enterprise_num), |
|---|
| 2865 | | _VendorClassDataField("vso", [], VENDOR_SPECIFIC_OPTION, |
|---|
| 2866 | | length_from = lambda pkt: pkt.optlen-4) ] |
|---|
| 2867 | | |
|---|
| 2868 | | #### DHCPv6 Interface-ID Option ##################################### |
|---|
| 2869 | | |
|---|
| 2870 | | # Repasser sur cette option a la fin. Elle a pas l'air d'etre des |
|---|
| 2871 | | # masses critique. |
|---|
| 2872 | | class DHCP6OptIfaceId(_DHCP6OptGuessPayload):# RFC sect 22.18 |
|---|
| 2873 | | name = "DHCP6 Interface-Id Option" |
|---|
| 2874 | | fields_desc = [ ShortEnumField("optcode", 18, dhcp6opts), |
|---|
| 2875 | | FieldLenField("optlen", None, fmt="!H", |
|---|
| 2876 | | length_of="ifaceid"), |
|---|
| 2877 | | StrLenField("ifaceid", "", |
|---|
| 2878 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2879 | | |
|---|
| 2880 | | |
|---|
| 2881 | | #### DHCPv6 Reconfigure Message Option ############################## |
|---|
| 2882 | | |
|---|
| 2883 | | # A server includes a Reconfigure Message option in a Reconfigure |
|---|
| 2884 | | # message to indicate to the client whether the client responds with a |
|---|
| 2885 | | # renew message or an Informatiion-request message. |
|---|
| 2886 | | class DHCP6OptReconfMsg(_DHCP6OptGuessPayload): # RFC sect 22.19 |
|---|
| 2887 | | name = "DHCP6 Reconfigure Message Option" |
|---|
| 2888 | | fields_desc = [ ShortEnumField("optcode", 19, dhcp6opts), |
|---|
| 2889 | | ShortField("optlen", 1 ), |
|---|
| 2890 | | ByteEnumField("msgtype", 11, { 5:"Renew Message", |
|---|
| 2891 | | 11:"Information Request"}) ] |
|---|
| 2892 | | |
|---|
| 2893 | | |
|---|
| 2894 | | #### DHCPv6 Reconfigure Accept Option ############################### |
|---|
| 2895 | | |
|---|
| 2896 | | # A client uses the Reconfigure Accept option to announce to the |
|---|
| 2897 | | # server whether the client is willing to accept Recoonfigure |
|---|
| 2898 | | # messages, and a server uses this option to tell the client whether |
|---|
| 2899 | | # or not to accept Reconfigure messages. The default behavior in the |
|---|
| 2900 | | # absence of this option, means unwillingness to accept reconfigure |
|---|
| 2901 | | # messages, or instruction not to accept Reconfigure messages, for the |
|---|
| 2902 | | # client and server messages, respectively. |
|---|
| 2903 | | class DHCP6OptReconfAccept(_DHCP6OptGuessPayload): # RFC sect 22.20 |
|---|
| 2904 | | name = "DHCP6 Reconfigure Accept Option" |
|---|
| 2905 | | fields_desc = [ ShortEnumField("optcode", 20, dhcp6opts), |
|---|
| 2906 | | ShortField("optlen", 0)] |
|---|
| 2907 | | |
|---|
| 2908 | | # As required in Sect 8. of RFC 3315, Domain Names must be encoded as |
|---|
| 2909 | | # described in section 3.1 of RFC 1035 |
|---|
| 2910 | | # XXX Label should be at most 63 octets in length : we do not enforce it |
|---|
| 2911 | | # Total length of domain should be 255 : we do not enforce it either |
|---|
| 2912 | | class DomainNameListField(StrLenField): |
|---|
| 2913 | | islist = 1 |
|---|
| 2914 | | |
|---|
| 2915 | | def i2len(self, pkt, x): |
|---|
| 2916 | | return len(self.i2m(pkt, x)) |
|---|
| 2917 | | |
|---|
| 2918 | | def m2i(self, pkt, x): |
|---|
| 2919 | | res = [] |
|---|
| 2920 | | while x: |
|---|
| 2921 | | cur = [] |
|---|
| 2922 | | while x and x[0] != '\x00': |
|---|
| 2923 | | l = ord(x[0]) |
|---|
| 2924 | | cur.append(x[1:l+1]) |
|---|
| 2925 | | x = x[l+1:] |
|---|
| 2926 | | res.append(".".join(cur)) |
|---|
| 2927 | | if x and x[0] == '\x00': |
|---|
| 2928 | | x = x[1:] |
|---|
| 2929 | | return res |
|---|
| 2930 | | |
|---|
| 2931 | | def i2m(self, pkt, x): |
|---|
| 2932 | | def conditionalTrailingDot(z): |
|---|
| 2933 | | if z and z[-1] == '\x00': |
|---|
| 2934 | | return z |
|---|
| 2935 | | return z+'\x00' |
|---|
| 2936 | | res = "" |
|---|
| 2937 | | tmp = map(lambda y: map((lambda z: chr(len(z))+z), y.split('.')), x) |
|---|
| 2938 | | return "".join(map(lambda x: conditionalTrailingDot("".join(x)), tmp)) |
|---|
| 2939 | | |
|---|
| 2940 | | class DHCP6OptSIPDomains(_DHCP6OptGuessPayload): #RFC3319 |
|---|
| 2941 | | name = "DHCP6 Option - SIP Servers Domain Name List" |
|---|
| 2942 | | fields_desc = [ ShortEnumField("optcode", 21, dhcp6opts), |
|---|
| 2943 | | FieldLenField("optlen", None, length_of="sipdomains"), |
|---|
| 2944 | | DomainNameListField("sipdomains", [], |
|---|
| 2945 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2946 | | |
|---|
| 2947 | | class DHCP6OptSIPServers(_DHCP6OptGuessPayload): #RFC3319 |
|---|
| 2948 | | name = "DHCP6 Option - SIP Servers IPv6 Address List" |
|---|
| 2949 | | fields_desc = [ ShortEnumField("optcode", 22, dhcp6opts), |
|---|
| 2950 | | FieldLenField("optlen", None, length_of="sipservers"), |
|---|
| 2951 | | IP6ListField("sipservers", [], |
|---|
| 2952 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2953 | | |
|---|
| 2954 | | class DHCP6OptDNSServers(_DHCP6OptGuessPayload): #RFC3646 |
|---|
| 2955 | | name = "DHCP6 Option - DNS Recursive Name Server" |
|---|
| 2956 | | fields_desc = [ ShortEnumField("optcode", 23, dhcp6opts), |
|---|
| 2957 | | FieldLenField("optlen", None, length_of="dnsservers"), |
|---|
| 2958 | | IP6ListField("dnsservers", [], |
|---|
| 2959 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2960 | | |
|---|
| 2961 | | class DHCP6OptDNSDomains(_DHCP6OptGuessPayload): #RFC3646 |
|---|
| 2962 | | name = "DHCP6 Option - Domain Search List option" |
|---|
| 2963 | | fields_desc = [ ShortEnumField("optcode", 24, dhcp6opts), |
|---|
| 2964 | | FieldLenField("optlen", None, length_of="dnsdomains"), |
|---|
| 2965 | | DomainNameListField("dnsdomains", [], |
|---|
| 2966 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2967 | | |
|---|
| 2968 | | # TODO: Implement iaprefopts correctly when provided with more |
|---|
| 2969 | | # information about it. |
|---|
| 2970 | | class DHCP6OptIAPrefix(_DHCP6OptGuessPayload): #RFC3633 |
|---|
| 2971 | | name = "DHCP6 Option - IA_PD Prefix option" |
|---|
| 2972 | | fields_desc = [ ShortEnumField("optcode", 26, dhcp6opts), |
|---|
| 2973 | | FieldLenField("optlen", None, length_of="iaprefopts", |
|---|
| 2974 | | adjust = lambda pkt,x: x+26), |
|---|
| 2975 | | IntField("preflft", 0), |
|---|
| 2976 | | IntField("validlft", 0), |
|---|
| 2977 | | ByteField("plen", 48), # TODO: Challenge that default value |
|---|
| 2978 | | IP6Field("prefix", "2001:db8::"), # At least, global and won't hurt |
|---|
| 2979 | | StrLenField("iaprefopts", "", |
|---|
| 2980 | | length_from = lambda pkt: pkt.optlen-26) ] |
|---|
| 2981 | | |
|---|
| 2982 | | class DHCP6OptIA_PD(_DHCP6OptGuessPayload): #RFC3633 |
|---|
| 2983 | | name = "DHCP6 Option - Identity Association for Prefix Delegation" |
|---|
| 2984 | | fields_desc = [ ShortEnumField("optcode", 25, dhcp6opts), |
|---|
| 2985 | | FieldLenField("optlen", None, length_of="iapdopt", |
|---|
| 2986 | | adjust = lambda pkt,x: x+12), |
|---|
| 2987 | | IntField("iaid", 0), |
|---|
| 2988 | | IntField("T1", 0), |
|---|
| 2989 | | IntField("T2", 0), |
|---|
| 2990 | | PacketListField("iapdopt", [], DHCP6OptIAPrefix, |
|---|
| 2991 | | length_from = lambda pkt: pkt.optlen-12) ] |
|---|
| 2992 | | |
|---|
| 2993 | | class DHCP6OptNISServers(_DHCP6OptGuessPayload): #RFC3898 |
|---|
| 2994 | | name = "DHCP6 Option - NIS Servers" |
|---|
| 2995 | | fields_desc = [ ShortEnumField("optcode", 27, dhcp6opts), |
|---|
| 2996 | | FieldLenField("optlen", None, length_of="nisservers"), |
|---|
| 2997 | | IP6ListField("nisservers", [], |
|---|
| 2998 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 2999 | | |
|---|
| 3000 | | class DHCP6OptNISPServers(_DHCP6OptGuessPayload): #RFC3898 |
|---|
| 3001 | | name = "DHCP6 Option - NIS+ Servers" |
|---|
| 3002 | | fields_desc = [ ShortEnumField("optcode", 28, dhcp6opts), |
|---|
| 3003 | | FieldLenField("optlen", None, length_of="nispservers"), |
|---|
| 3004 | | IP6ListField("nispservers", [], |
|---|
| 3005 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 3006 | | |
|---|
| 3007 | | class DomainNameField(StrLenField): |
|---|
| 3008 | | def getfield(self, pkt, s): |
|---|
| 3009 | | l = self.length_from(pkt) |
|---|
| 3010 | | return s[l:], self.m2i(pkt,s[:l]) |
|---|
| 3011 | | |
|---|
| 3012 | | def i2len(self, pkt, x): |
|---|
| 3013 | | return len(self.i2m(pkt, x)) |
|---|
| 3014 | | |
|---|
| 3015 | | def m2i(self, pkt, x): |
|---|
| 3016 | | save = x |
|---|
| 3017 | | cur = [] |
|---|
| 3018 | | while x and x[0] != '\x00': |
|---|
| 3019 | | l = ord(x[0]) |
|---|
| 3020 | | cur.append(x[1:1+l]) |
|---|
| 3021 | | x = x[l+1:] |
|---|
| 3022 | | if x[0] != '\x00': |
|---|
| 3023 | | print "Found weird domain: '%s'. Keeping %s" % (save, x) |
|---|
| 3024 | | return ".".join(cur) |
|---|
| 3025 | | |
|---|
| 3026 | | def i2m(self, pkt, x): |
|---|
| 3027 | | def conditionalTrailingDot(z): |
|---|
| 3028 | | if (z and z[-1] == '\x00'): |
|---|
| 3029 | | return z |
|---|
| 3030 | | return z+'\x00' |
|---|
| 3031 | | if not x: |
|---|
| 3032 | | return "" |
|---|
| 3033 | | tmp = "".join(map(lambda z: chr(len(z))+z, x.split('.'))) |
|---|
| 3034 | | return conditionalTrailingDot(tmp) |
|---|
| 3035 | | |
|---|
| 3036 | | class DHCP6OptNISDomain(_DHCP6OptGuessPayload): #RFC3898 |
|---|
| 3037 | | name = "DHCP6 Option - NIS Domain Name" |
|---|
| 3038 | | fields_desc = [ ShortEnumField("optcode", 29, dhcp6opts), |
|---|
| 3039 | | FieldLenField("optlen", None, length_of="nisdomain"), |
|---|
| 3040 | | DomainNameField("nisdomain", "", |
|---|
| 3041 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 3042 | | |
|---|
| 3043 | | class DHCP6OptNISPDomain(_DHCP6OptGuessPayload): #RFC3898 |
|---|
| 3044 | | name = "DHCP6 Option - NIS+ Domain Name" |
|---|
| 3045 | | fields_desc = [ ShortEnumField("optcode", 30, dhcp6opts), |
|---|
| 3046 | | FieldLenField("optlen", None, length_of="nispdomain"), |
|---|
| 3047 | | DomainNameField("nispdomain", "", |
|---|
| 3048 | | length_from= lambda pkt: pkt.optlen) ] |
|---|
| 3049 | | |
|---|
| 3050 | | class DHCP6OptSNTPServers(_DHCP6OptGuessPayload): #RFC4075 |
|---|
| 3051 | | name = "DHCP6 option - SNTP Servers" |
|---|
| 3052 | | fields_desc = [ ShortEnumField("optcode", 31, dhcp6opts), |
|---|
| 3053 | | FieldLenField("optlen", None, length_of="sntpservers"), |
|---|
| 3054 | | IP6ListField("sntpservers", [], |
|---|
| 3055 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 3056 | | |
|---|
| 3057 | | IRT_DEFAULT=86400 |
|---|
| 3058 | | IRT_MINIMUM=600 |
|---|
| 3059 | | class DHCP6OptInfoRefreshTime(_DHCP6OptGuessPayload): #RFC4242 |
|---|
| 3060 | | name = "DHCP6 Option - Information Refresh Time" |
|---|
| 3061 | | fields_desc = [ ShortEnumField("optcode", 32, dhcp6opts), |
|---|
| 3062 | | ShortField("optlen", 4), |
|---|
| 3063 | | IntField("reftime", IRT_DEFAULT)] # One day |
|---|
| 3064 | | |
|---|
| 3065 | | class DHCP6OptBCMCSDomains(_DHCP6OptGuessPayload): #RFC4280 |
|---|
| 3066 | | name = "DHCP6 Option - BCMCS Domain Name List" |
|---|
| 3067 | | fields_desc = [ ShortEnumField("optcode", 33, dhcp6opts), |
|---|
| 3068 | | FieldLenField("optlen", None, length_of="bcmcsdomains"), |
|---|
| 3069 | | DomainNameListField("bcmcsdomains", [], |
|---|
| 3070 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 3071 | | |
|---|
| 3072 | | class DHCP6OptBCMCSServers(_DHCP6OptGuessPayload): #RFC4280 |
|---|
| 3073 | | name = "DHCP6 Option - BCMCS Addresses List" |
|---|
| 3074 | | fields_desc = [ ShortEnumField("optcode", 34, dhcp6opts), |
|---|
| 3075 | | FieldLenField("optlen", None, length_of="bcmcsservers"), |
|---|
| 3076 | | IP6ListField("bcmcsservers", [], |
|---|
| 3077 | | length_from= lambda pkt: pkt.optlen) ] |
|---|
| 3078 | | |
|---|
| 3079 | | # TODO : Does Nothing at the moment |
|---|
| 3080 | | class DHCP6OptGeoConf(_DHCP6OptGuessPayload): #RFC-ietf-geopriv-dhcp-civil-09.txt |
|---|
| 3081 | | name = "" |
|---|
| 3082 | | fields_desc = [ ShortEnumField("optcode", 36, dhcp6opts), |
|---|
| 3083 | | FieldLenField("optlen", None, length_of="optdata"), |
|---|
| 3084 | | StrLenField("optdata", "", |
|---|
| 3085 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 3086 | | |
|---|
| 3087 | | # TODO: see if we encounter opaque values from vendor devices |
|---|
| 3088 | | class DHCP6OptRemoteID(_DHCP6OptGuessPayload): #RFC4649 |
|---|
| 3089 | | name = "DHCP6 Option - Relay Agent Remote-ID" |
|---|
| 3090 | | fields_desc = [ ShortEnumField("optcode", 37, dhcp6opts), |
|---|
| 3091 | | FieldLenField("optlen", None, length_of="remoteid", |
|---|
| 3092 | | adjust = lambda pkt,x: x+4), |
|---|
| 3093 | | IntEnumField("enterprisenum", None, iana_enterprise_num), |
|---|
| 3094 | | StrLenField("remoteid", "", |
|---|
| 3095 | | length_from = lambda pkt: pkt.optlen-4) ] |
|---|
| 3096 | | |
|---|
| 3097 | | # TODO : 'subscriberid' default value should be at least 1 byte long |
|---|
| 3098 | | class DHCP6OptSubscriberID(_DHCP6OptGuessPayload): #RFC4580 |
|---|
| 3099 | | name = "DHCP6 Option - Subscriber ID" |
|---|
| 3100 | | fields_desc = [ ShortEnumField("optcode", 38, dhcp6opts), |
|---|
| 3101 | | FieldLenField("optlen", None, length_of="subscriberid"), |
|---|
| 3102 | | StrLenField("subscriberid", "", |
|---|
| 3103 | | length_from = lambda pkt: pkt.optlen) ] |
|---|
| 3104 | | |
|---|
| 3105 | | # TODO : "The data in the Domain Name field MUST be encoded |
|---|
| 3106 | | # as described in Section 8 of [5]" |
|---|
| 3107 | | class DHCP6OptClientFQDN(_DHCP6OptGuessPayload): #RFC4704 |
|---|
| 3108 | | name = "DHCP6 Option - Client FQDN" |
|---|
| 3109 | | fields_desc = [ ShortEnumField("optcode", 39, dhcp6opts), |
|---|
| 3110 | | FieldLenField("optlen", None, length_of="fqdn", |
|---|
| 3111 | | adjust = lambda pkt,x: x+1), |
|---|
| 3112 | | BitField("res", 0, 5), |
|---|
| 3113 | | FlagsField("flags", 0, 3, "SON" ), |
|---|
| 3114 | | DomainNameField("fqdn", "", |
|---|
| 3115 | | length_from = lambda pkt: pkt.optlen-1) ] |
|---|
| 3116 | | |
|---|
| 3117 | | class DHCP6OptRelayAgentERO(_DHCP6OptGuessPayload): # RFC4994 |
|---|
| 3118 | | name = "DHCP6 Option - RelayRequest Option" |
|---|
| 3119 | | fields_desc = [ ShortEnumField("optcode", 43, dhcp6opts), |
|---|
| 3120 | | Field |
|---|