From df9976aef0282a0bf4f462a205416da0a74f3a58 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 13 Feb 2005 22:10:03 +0000 Subject: [PATCH] 2005-02-13 Dan Williams Patch from Dan Reed: DHCP options D-BUS API Exposes the DHCP options that a device receives to clients over D-BUS. * configure.in - A few cleanups * dhcpcd/client.h - Correct names, option length, and types for DHCP options * dhcpcd/dhcpcd.[ch] - Clarify function names that access DHCP options & data * src/NetworkManagerDHCP.c - Use new DHCP data access functions * src/NetworkManagerDbus.c - Message handler for DHCP functions * src/nm-dbus-dhcp.[ch] (new) - DHCP dbus methods * test/nm-dhcp-opt-test.c - Test DHCP D-BUS API and return all present DHCP options git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@444 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 26 ++ NetworkManager.h | 2 + configure.in | 35 +-- dhcpcd/client.h | 200 +++++++++++----- dhcpcd/dhcpcd.c | 62 ++++- dhcpcd/dhcpcd.h | 29 ++- src/Makefile.am | 10 +- src/NetworkManagerDHCP.c | 28 +-- src/NetworkManagerDbus.c | 92 +++++--- src/NetworkManagerDbusUtils.h | 3 + src/NetworkManagerDevice.h | 1 + src/NetworkManagerMain.h | 1 + src/nm-dbus-dhcp.c | 431 ++++++++++++++++++++++++++++++++++ src/nm-dbus-dhcp.h | 29 +++ test/.cvsignore | 1 + test/Makefile.am | 7 +- test/nm-dhcp-opt-test.c | 374 +++++++++++++++++++++++++++++ 17 files changed, 1183 insertions(+), 148 deletions(-) create mode 100644 src/nm-dbus-dhcp.c create mode 100644 src/nm-dbus-dhcp.h create mode 100644 test/nm-dhcp-opt-test.c diff --git a/ChangeLog b/ChangeLog index 986e4fa6c9..8ca620d3c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2005-02-13 Dan Williams + + Patch from Dan Reed: DHCP options D-BUS API + Exposes the DHCP options that a device receives to clients over D-BUS. + + * configure.in + - A few cleanups + + * dhcpcd/client.h + - Correct names, option length, and types for DHCP options + + * dhcpcd/dhcpcd.[ch] + - Clarify function names that access DHCP options & data + + * src/NetworkManagerDHCP.c + - Use new DHCP data access functions + + * src/NetworkManagerDbus.c + - Message handler for DHCP functions + + * src/nm-dbus-dhcp.[ch] (new) + - DHCP dbus methods + + * test/nm-dhcp-opt-test.c + - Test DHCP D-BUS API and return all present DHCP options + 2005-02-12 Dan Williams * test/Makefile.am diff --git a/NetworkManager.h b/NetworkManager.h index 08e4de4c2d..c9d70f0960 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -31,6 +31,8 @@ #define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" #define NM_DBUS_PATH_DEVICES "/org/freedesktop/NetworkManager/Devices" #define NM_DBUS_INTERFACE_DEVICES "org.freedesktop.NetworkManager.Devices" +#define NM_DBUS_PATH_DHCP "/org/freedesktop/NetworkManager/DhcpOptions" +#define NM_DBUS_INTERFACE_DHCP "org.freedesktop.NetworkManager.DhcpOptions" #define NMI_DBUS_SERVICE "org.freedesktop.NetworkManagerInfo" #define NMI_DBUS_PATH "/org/freedesktop/NetworkManagerInfo" diff --git a/configure.in b/configure.in index 04bf27216a..b91bbf56ae 100644 --- a/configure.in +++ b/configure.in @@ -39,17 +39,7 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package]) ALL_LINGUAS="bs cs da de el en_CA es gu ja nb nl no pa pt_BR sk sq sv wa zh_CN" AM_GLIB_GNU_GETTEXT -AC_ARG_WITH(distro, -[ - --with-distro: Specify the Linux distribution to target with distro-specific - parts of NetworkManager - --with-distro=redhat - --with-distro=gentoo - --with-distro=debian - --with-distro=mandrake - --with-distro=slackware -],,) - +AC_ARG_WITH(distro, AC_HELP_STRING([--with-distro=DISTRO], [Specify the Linux distribution to target: One of redhat, gentoo, debian, or slackware])) if test "z$with_distro" = "z"; then AC_CHECK_FILE(/etc/mandrake-release,with_distro="mandrake") AC_CHECK_FILE(/etc/redhat-release,with_distro="redhat") @@ -61,13 +51,13 @@ fi with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]' ` if test "z$with_distro" = "z"; then - echo "Linux distribution autodetection failed, you must specify the distribution to target using --with-distro=" + echo "Linux distribution autodetection failed, you must specify the distribution to target using --with-distro=DISTRO" exit 1 else case $with_distro in redhat|gentoo|debian|slackware) ;; *) - echo "Your distribution(${with_distro}) is not yet supported! (patches welcome)" + echo "Your distribution (${with_distro}) is not yet supported! (patches welcome)" exit 1 ;; esac @@ -148,7 +138,7 @@ PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1) AC_SUBST(GNOME_KEYRING_CFLAGS) AC_SUBST(GNOME_KEYRING_LIBS) -AC_ARG_WITH(gcrypt, [--with-gcrypt Use gcrypt library], ac_gcrypt=$withval, ac_gcrypt=auto) +AC_ARG_WITH(gcrypt, AC_HELP_STRING([--with-gcrypt], [Use gcrypt library]), ac_gcrypt=$withval, ac_gcrypt=auto) if test x"$ac_gcrypt" != xno; then AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) else @@ -175,11 +165,10 @@ AC_SUBST(PANEL_APPLET_CFLAGS) AC_SUBST(PANEL_APPLET_LIBS) PKG_CHECK_MODULES(LIBGNOMEUI, libgnomeui-2.0) -AC_SUBST(LIBGNOMEUI_CFLAFS) +AC_SUBST(LIBGNOMEUI_CFLAGS) # is this even needed? it was typed incorrectly before AC_SUBST(LIBGNOMEUI_LIBS) -# taken from hal -AC_ARG_WITH(dbus-sys, [ --with-dbus-sys= where D-BUS system.d directory is]) +AC_ARG_WITH(dbus-sys, AC_HELP_STRING([--with-dbus-sys=DIR], [where D-BUS system.d directory is])) if ! test -z "$with_dbus_sys" ; then DBUS_SYS_DIR="$with_dbus_sys" @@ -189,9 +178,9 @@ fi AC_SUBST(DBUS_SYS_DIR) AC_DEFINE_UNQUOTED(DBUS_SYSTEMD_DIR, "$DBUS_SYS_DIR", [Where system.d dir for DBUS is]) -AC_ARG_WITH(named, AC_HELP_STRING([--with-named=], [path to the named binary])) -AC_ARG_WITH(named_dir, AC_HELP_STRING([--with-named-dir=], [path to the named data directory])) -AC_ARG_WITH(named_user, AC_HELP_STRING([--with-named-user=username], [named username])) +AC_ARG_WITH(named, AC_HELP_STRING([--with-named=PATH], [path to the named binary])) +AC_ARG_WITH(named_dir, AC_HELP_STRING([--with-named-dir=PATH], [path to the named data directory])) +AC_ARG_WITH(named_user, AC_HELP_STRING([--with-named-user=USERNAME], [named username])) if test "x${with_named}" = x; then AC_DEFINE(NM_NO_NAMED,,[Define if you want to disable named support]) fi @@ -199,7 +188,7 @@ AC_DEFINE_UNQUOTED(NM_NAMED_BINARY_PATH, "$with_named", [Define to path of named AC_DEFINE_UNQUOTED(NM_NAMED_DATA_DIR, "$with_named_dir", [Define to path of named data directory]) AC_DEFINE_UNQUOTED(NM_NAMED_USER, "$with_named_user", [Define to named username]) -AC_ARG_ENABLE(notification-icon, [ --enable-notification-icon builds the wireless applet as a notification icon], enable_notification_icon=$enableval, enable_notification_icon=yes) +AC_ARG_ENABLE(notification-icon, AC_HELP_STRING([--enable-notification-icon], [builds the wireless applet as a notification icon]), enable_notification_icon=$enableval, enable_notification_icon=yes) AM_CONDITIONAL(BUILD_NOTIFICATION_ICON, test x$enable_notification_icon = xyes) if test x$enable_notification_icon == xyes ; then @@ -240,7 +229,7 @@ prefix=$old_prefix exec_prefix=$old_exec_prefix AC_ARG_ENABLE(more-warnings, -[ --enable-more-warnings Maximum compiler warnings], +AC_HELP_STRING([--enable-more-warnings], [Maximum compiler warnings]), set_more_warnings="$enableval",[ if test -d "$srcdir/{arch}" || test -d "$srcdir/CVS"; then set_more_warnings=yes @@ -295,4 +284,4 @@ libnm_glib/libnm_glib.pc echo echo Distribution targeting: ${with_distro} -echo 'if this is not correct, please specifiy your distro with --with-distro=' +echo 'if this is not correct, please specifiy your distro with --with-distro=DISTRO' diff --git a/dhcpcd/client.h b/dhcpcd/client.h index d96964324f..c7702b25cd 100644 --- a/dhcpcd/client.h +++ b/dhcpcd/client.h @@ -83,9 +83,9 @@ typedef struct dhcpMessage typedef struct dhcpOptions { - u_char num; u_char len[256]; void *val[256]; + u_char num; } __attribute__((packed)) dhcpOptions; struct packed_ether_header @@ -132,75 +132,145 @@ typedef struct dhcp_interface typedef struct dhcp_option_table { - const int option; - const char *name; - const int len; + const char *name; + const int len_hint; + dhcp_option_type type; } dhcp_option_table; static dhcp_option_table dhcp_opt_table[] = { - { padOption, "padOption", 1 }, - { subnetMask, "subnetMask", 4 }, - { timerOffset, "timerOffset", -1 }, - { routersOnSubnet, "routersOnSubnet", 4 }, - { timeServer, "timeServer", 4 }, - { nameServer, "nameServer", 4 }, - { dns, "dns", 4 }, - { logServer, "logServer", 4 }, - { cookieServer, "cookieServer", 4 }, - { lprServer, "lprServer", 4 }, - { impressServer, "impressServer", 4 }, - { resourceLocationServer,"resourceLocationServer",4 }, - { hostName, "hostName", -1 }, - { bootFileSize, "bootFileSize", 4 }, - { meritDumpFile, "meritDumpFile", 4 }, - { domainName, "domainName", -1 }, - { swapServer, "swapServer", 4 }, - { rootPath, "rootPath", -1 }, - { extentionsPath, "extentionsPath", -1 }, - { IPforwarding, "IPforwarding", -1 }, - { nonLocalSourceRouting, "nonLocalSourceRouting", -1 }, - { policyFilter, "policyFilter", -1 }, - { maxDgramReasmSize, "maxDgramReasmSize", -1 }, - { defaultIPTTL, "defaultIPTTL", -1 }, - { pathMTUagingTimeout, "pathMTUagingTimeout", -1 }, - { pathMTUplateauTable, "pathMTUplateauTable", -1 }, - { ifMTU, "ifMTU", -1 }, - { allSubnetsLocal, "allSubnetsLocal", -1 }, - { broadcastAddr, "broadcastAddr", 4 }, - { performMaskDiscovery, "performMaskDiscovery", -1 }, - { routerSolicitationAddr,"routerSolicitationAddr",-1 }, - { staticRoute, "staticRoute", 4 }, - { trailerEncapsulation, "trailerEncapsulation", -1 }, - { arpCacheTimeout, "arpCacheTimeout", -1 }, - { ethernetEncapsulation, "ethernetEncapsulation", -1 }, - { tcpDefaultTTL, "tcpDefaultTTL", -1 }, - { tcpKeepaliveInterval, "tcpKeepaliveInterval", -1 }, - { tcpKeepaliveGarbage, "tcpKeepaliveGarbage", -1 }, - { nisDomainName, "nisDomainName", -1 }, - { nisServers, "nisServers", 4 }, - { ntpServers, "ntpServers", 4 }, - { vendorSpecificInfo, "vendorSpecificInfo", -1 }, - { netBIOSnameServer, "netBIOSnameServer", -1 }, - { netBIOSdgramDistServer,"netBIOSdgramDistServer",-1 }, - { netBIOSnodeType, "netBIOSnodeType", -1 }, - { netBIOSscope, "netBIOSscope", -1 }, - { xFontServer, "xFontServer", -1 }, - { xDisplayManager, "xDisplayManager", -1 }, - { dhcpRequestedIPaddr, "dhcpRequestedIPaddr", 4 }, - { dhcpIPaddrLeaseTime, "dhcpIPaddrLeaseTime", 4 }, - { dhcpOptionOverload, "dhcpOptionOverload", -1 }, - { dhcpMessageType, "dhcpMessageType", -1 }, - { dhcpServerIdentifier, "dhcpServerIdentifier", -1 }, - { dhcpParamRequest, "dhcpParamRequest", -1 }, - { dhcpMsg, "dhcpMsg", -1 }, - { dhcpMaxMsgSize, "dhcpMaxMsgSize", -1 }, - { dhcpT1value, "dhcpT1value", 4 }, - { dhcpT2value, "dhcpT2value", 4 }, - { dhcpClassIdentifier, "dhcpClassIdentifier", -1 }, - { dhcpClientIdentifier, "dhcpClientIdentifier", -1 }, - { -1, NULL, -1 } +/* Names come from http://www.iana.org/assignments/bootp-dhcp-parameters, not to be changed */ + +/* 0 */ { "Pad", 0, DHCP_OPT_INVALID }, +/* 1 */ { "Subnet Mask", 4, DHCP_OPT_ADDRESS }, +/* 2 */ { "Time Offset", 4, DHCP_OPT_TIME }, +/* 3 */ { "Router", 4, DHCP_OPT_ADDRESS }, +/* 4 */ { "Time Server", 4, DHCP_OPT_ADDRESS }, +/* 5 */ { "Name Server", 4, DHCP_OPT_ADDRESS }, +/* 6 */ { "Domain Server", 4, DHCP_OPT_ADDRESS }, +/* 7 */ { "Log Server", 4, DHCP_OPT_ADDRESS }, +/* 8 */ { "Quotes Server", 4, DHCP_OPT_ADDRESS }, +/* 9 */ { "LPR Server", 4, DHCP_OPT_ADDRESS }, +/* 10 */ { "Impress Server", 4, DHCP_OPT_ADDRESS }, +/* 11 */ { "RLP Server", 4, DHCP_OPT_ADDRESS }, +/* 12 */ { "Hostname", 1, DHCP_OPT_STRING }, +/* 13 */ { "Boot File Size", 2, DHCP_OPT_COUNT }, +/* 14 */ { "Merit Dump File", 1, DHCP_OPT_STRING }, +/* 15 */ { "Domain Name", 1, DHCP_OPT_STRING }, +/* 16 */ { "Swap Server", 1, DHCP_OPT_ADDRESS }, +/* 17 */ { "Root Path", 1, DHCP_OPT_STRING }, +/* 18 */ { "Extension Path", 1, DHCP_OPT_STRING }, +/* 19 */ { "Forward On/Off", 1, DHCP_OPT_TOGGLE }, +/* 20 */ { "SrcRte On/Off", 1, DHCP_OPT_TOGGLE }, +/* 21 */ { "Policy Filter", 1, DHCP_OPT_BLOB }, +/* 22 */ { "Max DG Assembly", 2, DHCP_OPT_COUNT }, +/* 23 */ { "Default IP TTL", 1, DHCP_OPT_COUNT }, +/* 24 */ { "MTU Timeout", 4, DHCP_OPT_TIME }, +/* 25 */ { "MTU Plateau", 1, DHCP_OPT_BLOB }, +/* 26 */ { "MTU Interface", 2, DHCP_OPT_COUNT }, +/* 27 */ { "MTU Subnet", 1, DHCP_OPT_TOGGLE }, +/* 28 */ { "Broadcast Address", 4, DHCP_OPT_ADDRESS }, +/* 29 */ { "Mask Discovery", 1, DHCP_OPT_TOGGLE }, +/* 30 */ { "Mask Supplier", 1, DHCP_OPT_TOGGLE }, +/* 31 */ { "Router Discovery", 1, DHCP_OPT_TOGGLE }, +/* 32 */ { "Router Request", 4, DHCP_OPT_ADDRESS }, +/* 33 */ { "Static Route", 1, DHCP_OPT_BLOB }, +/* 34 */ { "Trailers", 1, DHCP_OPT_TOGGLE }, +/* 35 */ { "ARP Timeout", 4, DHCP_OPT_TIME }, +/* 36 */ { "Ethernet", 1, DHCP_OPT_BLOB }, +/* 37 */ { "Default TCP TTL", 1, DHCP_OPT_COUNT}, +/* 38 */ { "Keepalive Time", 4, DHCP_OPT_TIME }, +/* 39 */ { "Keepalive Data", 1, DHCP_OPT_BLOB }, +/* 40 */ { "NIS Domain", 1, DHCP_OPT_STRING }, +/* 41 */ { "NIS Servers", 4, DHCP_OPT_ADDRESS }, +/* 42 */ { "NTP Servers", 4, DHCP_OPT_ADDRESS }, +/* 43 */ { "Vendor Specific", 1, DHCP_OPT_BLOB }, +/* 44 */ { "NETBIOS Name Srv", 4, DHCP_OPT_ADDRESS }, +/* 45 */ { "NETBIOS Dist Srv", 4, DHCP_OPT_ADDRESS }, +/* 46 */ { "NETBIOS Node Type", 1, DHCP_OPT_NUMBER }, +/* 47 */ { "NETBIOS Scope", 1, DHCP_OPT_NUMBER }, +/* 48 */ { "X Window Font", 4, DHCP_OPT_ADDRESS }, +/* 49 */ { "X Window Manager", 4, DHCP_OPT_ADDRESS }, +/* 50 */ { "Address Request", 4, DHCP_OPT_ADDRESS }, +/* 51 */ { "Address Time", 4, DHCP_OPT_TIME }, +/* 52 */ { "Overload", 1, DHCP_OPT_BLOB }, +/* 53 */ { "DHCP Msg Type", 1, DHCP_OPT_NUMBER }, +/* 54 */ { "DHCP Server Id", 4, DHCP_OPT_ADDRESS }, +/* 55 */ { "Parameter List", 1, DHCP_OPT_BLOB }, +/* 56 */ { "DHCP Message", 1, DHCP_OPT_BLOB }, +/* 57 */ { "DHCP Max Msg Size", 2, DHCP_OPT_COUNT }, +/* 58 */ { "Renewal Time", 4, DHCP_OPT_TIME }, +/* 59 */ { "Rebinding Time", 4, DHCP_OPT_TIME }, +/* 60 */ { "Class Id", 1, DHCP_OPT_BLOB }, +/* 61 */ { "Client Id", 1, DHCP_OPT_BLOB }, +/* 62 */ { "NetWare/IP Domain", 1, DHCP_OPT_STRING }, +/* 63 */ { "NetWare/IP Option", 1, DHCP_OPT_BLOB }, +/* 64 */ { "NIS-Domain-Name", 1, DHCP_OPT_STRING }, +/* 65 */ { "NIS-Server-Addr", 4, DHCP_OPT_ADDRESS }, +/* 66 */ { "Server-Name", 1, DHCP_OPT_STRING }, +/* 67 */ { "Bootfile-Name", 1, DHCP_OPT_STRING }, +/* 68 */ { "Home-Agent-Addrs", 4, DHCP_OPT_ADDRESS }, +/* 69 */ { "SMTP-Server", 4, DHCP_OPT_ADDRESS }, +/* 70 */ { "POP3-Server", 4, DHCP_OPT_ADDRESS }, +/* 71 */ { "NNTP-Server", 4, DHCP_OPT_ADDRESS }, +/* 72 */ { "WWW-Server", 4, DHCP_OPT_ADDRESS }, +/* 73 */ { "Finger-Server", 4, DHCP_OPT_ADDRESS }, +/* 74 */ { "IRC-Server", 4, DHCP_OPT_ADDRESS }, +/* 75 */ { "StreetTalk-Server", 4, DHCP_OPT_ADDRESS }, +/* 76 */ { "STDA-Server", 4, DHCP_OPT_ADDRESS }, +/* 77 */ { "User-Class", 1, DHCP_OPT_BLOB }, +/* 78 */ { "Directory Agent", 1, DHCP_OPT_BLOB }, +/* 79 */ { "Service Scope", 1, DHCP_OPT_BLOB }, +/* 80 */ { "Rapid Commit", 0, DHCP_OPT_BLOB }, +/* 81 */ { "Client FQDN", 1, DHCP_OPT_STRING }, +/* 82 */ { "Relay Agent Information", 1, DHCP_OPT_BLOB }, +/* 83 */ { "iSNS", 1, DHCP_OPT_BLOB }, +/* 84 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 85 */ { "NDS Servers", 4, DHCP_OPT_ADDRESS }, +/* 86 */ { "NDS Tree Name", 1, DHCP_OPT_BLOB }, +/* 87 */ { "NDS Context", 1, DHCP_OPT_BLOB }, +/* 88 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 89 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 90 */ { "Authentication", 1, DHCP_OPT_BLOB }, +/* 91 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 92 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 93 */ { "Client System", 1, DHCP_OPT_BLOB }, +/* 94 */ { "Client NDI", 1, DHCP_OPT_BLOB }, +/* 95 */ { "LDAP", 1, DHCP_OPT_BLOB }, +/* 96 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 97 */ { "UUID/GUID", 1, DHCP_OPT_BLOB }, +/* 98 */ { "User-Auth", 1, DHCP_OPT_BLOB }, +/* 99 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 100 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 101 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 102 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 103 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 104 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 105 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 106 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 107 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 108 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 109 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 110 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 111 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 112 */ { "Netinfo Address", 1, DHCP_OPT_BLOB }, +/* 113 */ { "Netinfo Tag", 1, DHCP_OPT_BLOB }, +/* 114 */ { "URL", 1, DHCP_OPT_STRING }, +/* 115 */ { NULL, 1, DHCP_OPT_BLOB }, +/* 116 */ { "Auto-Config", 1, DHCP_OPT_BLOB }, +/* 117 */ { "Name Service Search", 1, DHCP_OPT_BLOB }, +/* 118 */ { "Subnet Selection Option", 4, DHCP_OPT_BLOB }, +/* 119 */ { "Domain Search", 1, DHCP_OPT_STRING }, +/* 120 */ { "SIP Servers DHCP Option", 1, DHCP_OPT_BLOB }, +/* 121 */ { "Classless Static Route Option", 1, DHCP_OPT_BLOB }, +/* 122 */ { "CCC", 1, DHCP_OPT_BLOB }, +/* 123 */ { "GeoConf Option", 16, DHCP_OPT_BLOB }, +/* 124 */ { "V-I Vendor Class", 1, DHCP_OPT_BLOB }, +/* 125 */ { "V-I Vendor-Specific Information", 1, DHCP_OPT_BLOB }, +/* 126 */ { NULL, 0, DHCP_OPT_INVALID }, +/* 127 */ { NULL, 0, DHCP_OPT_INVALID }, }; +static const int dhcp_opt_table_len = sizeof(dhcp_opt_table)/sizeof(*dhcp_opt_table); typedef udpipMessage *(*dhcp_msg_build_proc)(dhcp_interface *, int *msg_len); diff --git a/dhcpcd/dhcpcd.c b/dhcpcd/dhcpcd.c index 4cd55860fb..e56c2da38c 100644 --- a/dhcpcd/dhcpcd.c +++ b/dhcpcd/dhcpcd.c @@ -260,7 +260,7 @@ void dhcp_interface_cease (dhcp_interface *iface) } /*****************************************************************************/ -int dhcp_interface_dhcp_field_exists (dhcp_interface *iface, int val) +int dhcp_interface_option_present (dhcp_interface *iface, int val) { if (!iface) return 0; @@ -268,7 +268,7 @@ int dhcp_interface_dhcp_field_exists (dhcp_interface *iface, int val) } /*****************************************************************************/ -void *dhcp_interface_get_dhcp_field (dhcp_interface *iface, int val) +void *dhcp_interface_option_payload (dhcp_interface *iface, int val) { if (!iface) return 0; @@ -276,7 +276,7 @@ void *dhcp_interface_get_dhcp_field (dhcp_interface *iface, int val) } /*****************************************************************************/ -int dhcp_interface_get_dhcp_field_len (dhcp_interface *iface, int val) +int dhcp_interface_option_len (dhcp_interface *iface, int val) { if (!iface) return 0; @@ -284,11 +284,61 @@ int dhcp_interface_get_dhcp_field_len (dhcp_interface *iface, int val) } /*****************************************************************************/ -int dhcp_individual_value_len (int val) +int dhcp_option_record_len (int val) { - if (val <= dhcpClientIdentifier) - return (dhcp_opt_table[val].len); + if ((val >= 0) && (val < dhcp_opt_table_len)) + return (dhcp_opt_table[val].len_hint); else return -1; } +/*****************************************************************************/ +const char *dhcp_option_name (int val) +{ + if ((val >= 0) && (val < dhcp_opt_table_len)) + return (dhcp_opt_table[val].name); + else + return NULL; +} + +/*****************************************************************************/ +dhcp_option_type dhcp_option_record_type (int val) +{ + if ((val >= 0) && (val < dhcp_opt_table_len)) + return (dhcp_opt_table[val].type); + else + return -1; +} + +/* case-insensitive alpha/num string comparison; skips over white space and punctuation */ +static int dhcp_strcmp (const unsigned char *s1, const unsigned char *s2) +{ + while (!isalnum(*s1) && (*s1 != 0)) + s1++; + while (!isalnum(*s2) && (*s2 != 0)) + s2++; + while (*s1 != 0) { + if (tolower(*s1) != tolower(*s2)) + return ((tolower(*s1) < tolower(*s2))?-1:1); + s1++; + s2++; + while (!isalnum(*s1) && (*s1 != 0)) + s1++; + while (!isalnum(*s2) && (*s2 != 0)) + s2++; + } + if (*s2 != 0) + return ((tolower(*s1) < tolower(*s2))?-1:1); + return (0); +} + +/*****************************************************************************/ +int dhcp_option_id_by_name (const char *name) +{ + int i; + + for (i = 0; i < dhcp_opt_table_len; i++) + if ((dhcp_opt_table[i].name != NULL) && (dhcp_strcmp (name, dhcp_opt_table[i].name) == 0)) + return (i); + return (-1); +} diff --git a/dhcpcd/dhcpcd.h b/dhcpcd/dhcpcd.h index b81316e23d..483e668aee 100644 --- a/dhcpcd/dhcpcd.h +++ b/dhcpcd/dhcpcd.h @@ -99,6 +99,18 @@ enum endOption = 255 }; +typedef enum dhcp_option_type +{ + DHCP_OPT_INVALID, + DHCP_OPT_ADDRESS, + DHCP_OPT_TIME, + DHCP_OPT_STRING, + DHCP_OPT_COUNT, + DHCP_OPT_TOGGLE, + DHCP_OPT_BLOB, + DHCP_OPT_NUMBER, +} dhcp_option_type; + /* Return codes */ #define RET_DHCP_ERROR 0 #define RET_DHCP_ADDRESS_IN_USE 1 @@ -122,13 +134,16 @@ typedef struct dhcp_client_options int window; } dhcp_client_options; -struct dhcp_interface *dhcp_interface_init (const char *if_name, dhcp_client_options *in_opts); -void dhcp_interface_free (struct dhcp_interface *iface); -void dhcp_interface_cease (struct dhcp_interface *iface); +struct dhcp_interface *dhcp_interface_init (const char *if_name, dhcp_client_options *in_opts); +void dhcp_interface_free (struct dhcp_interface *iface); +void dhcp_interface_cease (struct dhcp_interface *iface); -int dhcp_interface_dhcp_field_exists (struct dhcp_interface *iface, int val); -int dhcp_interface_get_dhcp_field_len (struct dhcp_interface *iface, int val); -void *dhcp_interface_get_dhcp_field (struct dhcp_interface *iface, int val); -int dhcp_individual_value_len (int val); +int dhcp_interface_option_present (struct dhcp_interface *iface, int val); +int dhcp_interface_option_len (struct dhcp_interface *iface, int val); +void *dhcp_interface_option_payload (struct dhcp_interface *iface, int val); +int dhcp_option_record_len (int val); +dhcp_option_type dhcp_option_record_type (int val); +int dhcp_option_id_by_name (const char *name); +const char * dhcp_option_name (int val); #endif diff --git a/src/Makefile.am b/src/Makefile.am index f07dbf49a6..47050cb52e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,12 +13,16 @@ NetworkManager_SOURCES = \ NetworkManagerDbus.h \ NetworkManagerDbusUtils.c \ NetworkManagerDbusUtils.h \ - nm-dbus-nm.h \ nm-dbus-nm.c \ - nm-dbus-device.h \ + nm-dbus-nm.h \ nm-dbus-device.c \ - nm-dbus-net.h \ + nm-dbus-device.h \ nm-dbus-net.c \ + nm-dbus-net.h \ + nm-dbus-dhcp.c \ + nm-dbus-dhcp.h \ + nm-dbus-nmi.c \ + nm-dbus-nmi.h \ NetworkManagerDHCP.c \ NetworkManagerDHCP.h \ NetworkManagerDevice.c \ diff --git a/src/NetworkManagerDHCP.c b/src/NetworkManagerDHCP.c index 2323926a01..c6691175e3 100644 --- a/src/NetworkManagerDHCP.c +++ b/src/NetworkManagerDHCP.c @@ -127,31 +127,31 @@ static void nm_device_dhcp_configure (NMDevice *dev) /* Replace basic info */ nm_system_device_set_ip4_address (dev, dev->dhcp_iface->ciaddr); - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, subnetMask)) + if (dhcp_interface_option_present (dev->dhcp_iface, subnetMask)) { - memcpy (&temp, dhcp_interface_get_dhcp_field (dev->dhcp_iface, subnetMask), dhcp_individual_value_len (subnetMask)); + memcpy (&temp, dhcp_interface_option_payload (dev->dhcp_iface, subnetMask), dhcp_option_record_len (subnetMask)); nm_system_device_set_ip4_netmask (dev, temp); } - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, broadcastAddr)) + if (dhcp_interface_option_present (dev->dhcp_iface, broadcastAddr)) { - memcpy (&temp, dhcp_interface_get_dhcp_field (dev->dhcp_iface, broadcastAddr), dhcp_individual_value_len (broadcastAddr)); + memcpy (&temp, dhcp_interface_option_payload (dev->dhcp_iface, broadcastAddr), dhcp_option_record_len (broadcastAddr)); nm_system_device_set_ip4_broadcast (dev, temp); } /* Default route */ - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, routersOnSubnet)) + if (dhcp_interface_option_present (dev->dhcp_iface, routersOnSubnet)) { - memcpy (&temp, dhcp_interface_get_dhcp_field (dev->dhcp_iface, routersOnSubnet), dhcp_individual_value_len (routersOnSubnet)); + memcpy (&temp, dhcp_interface_option_payload (dev->dhcp_iface, routersOnSubnet), dhcp_option_record_len (routersOnSubnet)); nm_system_device_set_ip4_default_route (dev, temp); } /* Update /etc/resolv.conf */ - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, dns)) - set_nameservers (dev, dhcp_interface_get_dhcp_field (dev->dhcp_iface, dns), dhcp_interface_get_dhcp_field_len (dev->dhcp_iface, dns)); + if (dhcp_interface_option_present (dev->dhcp_iface, dns)) + set_nameservers (dev, dhcp_interface_option_payload (dev->dhcp_iface, dns), dhcp_interface_option_len (dev->dhcp_iface, dns)); - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, domainName)) - set_domain_search (dev, dhcp_interface_get_dhcp_field (dev->dhcp_iface, domainName)); + if (dhcp_interface_option_present (dev->dhcp_iface, domainName)) + set_domain_search (dev, dhcp_interface_option_payload (dev->dhcp_iface, domainName)); } @@ -263,14 +263,14 @@ gboolean nm_device_dhcp_setup_timeouts (NMDevice *dev) g_return_val_if_fail (dev != NULL, FALSE); - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, dhcpT1value)) + if (dhcp_interface_option_present (dev->dhcp_iface, dhcpT1value)) { - memcpy (&t1, dhcp_interface_get_dhcp_field (dev->dhcp_iface, dhcpT1value), sizeof (int)); + memcpy (&t1, dhcp_interface_option_payload (dev->dhcp_iface, dhcpT1value), sizeof (int)); t1 = ntohl (t1); } - if (dhcp_interface_dhcp_field_exists (dev->dhcp_iface, dhcpT2value)) + if (dhcp_interface_option_present (dev->dhcp_iface, dhcpT2value)) { - memcpy (&t2, dhcp_interface_get_dhcp_field (dev->dhcp_iface, dhcpT2value), sizeof (int)); + memcpy (&t2, dhcp_interface_option_payload (dev->dhcp_iface, dhcpT2value), sizeof (int)); t2 = ntohl (t2); } if (!t1 || !t2) diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index bf41aa7b85..2f883529d5 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -38,6 +38,7 @@ #include "nm-dbus-nm.h" #include "nm-dbus-device.h" #include "nm-dbus-net.h" +#include "nm-dbus-dhcp.h" /* @@ -979,6 +980,41 @@ static DBusHandlerResult nm_dbus_devices_message_handler (DBusConnection *connec } +/* + * nm_dbus_dhcp_message_handler + * + * Dispatch messages against our NetworkManager DHCP object + * + * All calls are in the form /NM_DBUS_PATH_DHCP->METHOD (STRING attribute) + * For example, /org/freedesktop/NetworkManager/DhcpOptions->getType ("Name Server") + * + */ +static DBusHandlerResult nm_dbus_dhcp_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + NMData *data = (NMData *)user_data; + gboolean handled = TRUE; + DBusMessage *reply = NULL; + NMDbusCBData cb_data; + + g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (data->dhcp_methods != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + cb_data.data = data; + cb_data.dev = NULL; + cb_data.opt_id = -1; + handled = nm_dbus_method_dispatch (data->dhcp_methods, connection, message, &cb_data, &reply); + if (reply) + { + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + } + + return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); +} + + /* * nm_dbus_is_info_daemon_running * @@ -1008,22 +1044,22 @@ gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection) */ DBusConnection *nm_dbus_init (NMData *data) { - DBusError dbus_error; + DBusError error; dbus_bool_t success; DBusConnection *connection; DBusObjectPathVTable nm_vtable = {NULL, &nm_dbus_nm_message_handler, NULL, NULL, NULL, NULL}; DBusObjectPathVTable devices_vtable = {NULL, &nm_dbus_devices_message_handler, NULL, NULL, NULL, NULL}; + DBusObjectPathVTable dhcp_vtable = {NULL, &nm_dbus_dhcp_message_handler, NULL, NULL, NULL, NULL}; dbus_connection_set_change_sigpipe (TRUE); - dbus_error_init (&dbus_error); - connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error); - if ((connection == NULL) || dbus_error_is_set (&dbus_error)) + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if ((connection == NULL) || dbus_error_is_set (&error)) { syslog (LOG_ERR, "nm_dbus_init() could not get the system bus. Make sure the message bus daemon is running?"); - if (dbus_error_is_set (&dbus_error)) - dbus_error_free (&dbus_error); - return (NULL); + connection = NULL; + goto out; } dbus_connection_set_exit_on_disconnect (connection, FALSE); @@ -1032,25 +1068,22 @@ DBusConnection *nm_dbus_init (NMData *data) data->nm_methods = nm_dbus_nm_methods_setup (); data->device_methods = nm_dbus_device_methods_setup (); data->net_methods = nm_dbus_net_methods_setup (); + data->dhcp_methods = nm_dbus_dhcp_methods_setup (); - success = dbus_connection_register_object_path (connection, NM_DBUS_PATH, &nm_vtable, data); - if (!success) + if ( !dbus_connection_register_object_path (connection, NM_DBUS_PATH, &nm_vtable, data) + || !dbus_connection_register_fallback (connection, NM_DBUS_PATH_DEVICES, &devices_vtable, data) + || !dbus_connection_register_object_path (connection, NM_DBUS_PATH_DHCP, &dhcp_vtable, data)) { - syslog (LOG_CRIT, "nm_dbus_init() could not register a handler for NetworkManager. Not enough memory?"); - return (NULL); - } - - success = dbus_connection_register_fallback (connection, NM_DBUS_PATH_DEVICES, &devices_vtable, data); - if (!success) - { - syslog (LOG_CRIT, "nm_dbus_init() could not register a handler for NetworkManager devices. Not enough memory?"); - return (NULL); + syslog (LOG_CRIT, "nm_dbus_init() could not register D-BUS handlers. Cannot continue."); + connection = NULL; + goto out; } if (!dbus_connection_add_filter (connection, nm_dbus_nmi_filter, data, NULL)) { syslog (LOG_CRIT, "nm_dbus_init() could not attach a dbus message filter. The NetworkManager dbus security policy may not be loaded. Restart dbus?"); - return (NULL); + connection = NULL; + goto out; } dbus_bus_add_match (connection, @@ -1058,23 +1091,26 @@ DBusConnection *nm_dbus_init (NMData *data) "interface='" NMI_DBUS_INTERFACE "'," "sender='" NMI_DBUS_SERVICE "'," "path='" NMI_DBUS_PATH "'", - &dbus_error); - dbus_error_free (&dbus_error); + NULL); dbus_bus_add_match(connection, "type='signal'," "interface='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "'," "sender='" DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "'", - &dbus_error); - dbus_error_free (&dbus_error); + NULL); - dbus_bus_acquire_service (connection, NM_DBUS_SERVICE, 0, &dbus_error); - if (dbus_error_is_set (&dbus_error)) + dbus_error_init (&error); + dbus_bus_acquire_service (connection, NM_DBUS_SERVICE, 0, &error); + if (dbus_error_is_set (&error)) { - syslog (LOG_ERR, "nm_dbus_init() could not acquire its service. dbus_bus_acquire_service() says: '%s'", dbus_error.message); - dbus_error_free (&dbus_error); - return (NULL); + syslog (LOG_ERR, "nm_dbus_init() could not acquire its service. dbus_bus_acquire_service() says: '%s'", error.message); + connection = NULL; + goto out; } +out: + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + return (connection); } diff --git a/src/NetworkManagerDbusUtils.h b/src/NetworkManagerDbusUtils.h index 7498646d60..c5c5ac1786 100644 --- a/src/NetworkManagerDbusUtils.h +++ b/src/NetworkManagerDbusUtils.h @@ -29,12 +29,15 @@ #include "NetworkManagerMain.h" #include "NetworkManagerDevice.h" +#include "dhcpcd/dhcpcd.h" typedef struct NMDbusCBData { NMData *data; NMDevice *dev; NMAccessPoint *ap; + int opt_id; + struct dhcp_interface *dhcp_iface; } NMDbusCBData; typedef DBusMessage* (*NMDbusMethod) (DBusConnection *, DBusMessage *, NMDbusCBData *); diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 371930b11e..def2cc93fb 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -92,6 +92,7 @@ gboolean nm_device_need_ap_switch (NMDevice *dev); void nm_device_freeze_best_ap (NMDevice *dev); void nm_device_unfreeze_best_ap (NMDevice *dev); gboolean nm_device_is_best_ap_frozen (NMDevice *dev); +struct dhcp_interface *nm_device_get_dhcp_iface (NMDevice *dev); char * nm_device_get_path_for_ap (NMDevice *dev, NMAccessPoint *ap); diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index e7052e598b..d40e2dc648 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -48,6 +48,7 @@ typedef struct NMData NMDbusMethodList *nm_methods; NMDbusMethodList *device_methods; NMDbusMethodList *net_methods; + NMDbusMethodList *dhcp_methods; GMainContext *main_context; GMainLoop *main_loop; diff --git a/src/nm-dbus-dhcp.c b/src/nm-dbus-dhcp.c new file mode 100644 index 0000000000..cb3189a0fb --- /dev/null +++ b/src/nm-dbus-dhcp.c @@ -0,0 +1,431 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#include "NetworkManagerDevice.h" +#include "NetworkManagerDbus.h" +#include "NetworkManagerAP.h" +#include "NetworkManagerAPList.h" +#include "NetworkManagerUtils.h" +#include "nm-dbus-dhcp.h" +#include "dhcpcd/dhcpcd.h" + +static int nm_dbus_dhcp_record_type (int id) +{ + switch (dhcp_option_record_type (id)) + { + case DHCP_OPT_INVALID: + return DBUS_TYPE_INVALID; + case DHCP_OPT_ADDRESS: + case DHCP_OPT_TIME: + case DHCP_OPT_COUNT: + case DHCP_OPT_NUMBER: + return DBUS_TYPE_UINT32; + case DHCP_OPT_STRING: + return DBUS_TYPE_STRING; + case DHCP_OPT_TOGGLE: + return DBUS_TYPE_BOOLEAN; + case DHCP_OPT_BLOB: + return DBUS_TYPE_BYTE; + } + g_assert_not_reached(); +} + +#define DBUS_REPLY_BYTYPE(Dtype, Ctype) do { \ + int __DBUS_REPLY_BYTYPE_len; \ + \ + if (dhcp_interface_option_present (dhcp_iface, data->opt_id) \ + && (sizeof (Ctype) >= (__DBUS_REPLY_BYTYPE_len = dhcp_option_record_len (data->opt_id))) \ + && ((reply = dbus_message_new_method_return (message)) != NULL)) \ + { \ + Ctype __DBUS_REPLY_BYTYPE_val; \ + void *__DBUS_REPLY_BYTYPE_blob; \ + \ + __DBUS_REPLY_BYTYPE_blob = dhcp_interface_option_payload (dhcp_iface, data->opt_id); \ + if (__DBUS_REPLY_BYTYPE_len == 1) \ + __DBUS_REPLY_BYTYPE_val = ((unsigned char *)__DBUS_REPLY_BYTYPE_blob)[0]; \ + else if (__DBUS_REPLY_BYTYPE_len == 2) \ + __DBUS_REPLY_BYTYPE_val = ((dbus_uint16_t *)__DBUS_REPLY_BYTYPE_blob)[0]; \ + else \ + __DBUS_REPLY_BYTYPE_val = ((dbus_uint32_t *)__DBUS_REPLY_BYTYPE_blob)[0]; \ + dbus_message_append_args (reply, Dtype, __DBUS_REPLY_BYTYPE_val, DBUS_TYPE_INVALID); \ + } \ + } while (0) + +#define DBUS_REPLY_BYTYPEV(Dtype, Ctype, Dappend) do { \ + int __DBUS_REPLY_BYTYPE_len; \ + \ + if (dhcp_interface_option_present (dhcp_iface, data->opt_id) \ + && (sizeof (Ctype) >= (__DBUS_REPLY_BYTYPE_len = dhcp_option_record_len (data->opt_id))) \ + && ((reply = dbus_message_new_method_return (message)) != NULL)) \ + { \ + DBusMessageIter __DBUS_REPLY_BYTYPE_iter, __DBUS_REPLY_BYTYPE_sub; \ + void *__DBUS_REPLY_BYTYPE_blob; \ + int __DBUS_REPLY_BYTYPE_i, __DBUS_REPLY_BYTYPE_count; \ + \ + __DBUS_REPLY_BYTYPE_blob = dhcp_interface_option_payload (dhcp_iface, data->opt_id); \ + __DBUS_REPLY_BYTYPE_count = dhcp_interface_option_len (dhcp_iface, data->opt_id) / __DBUS_REPLY_BYTYPE_len; \ + dbus_message_iter_init (reply, &__DBUS_REPLY_BYTYPE_iter); \ + dbus_message_iter_append_array (&__DBUS_REPLY_BYTYPE_iter, &__DBUS_REPLY_BYTYPE_sub, Dtype); \ + for (__DBUS_REPLY_BYTYPE_i = 0; __DBUS_REPLY_BYTYPE_i < __DBUS_REPLY_BYTYPE_count; __DBUS_REPLY_BYTYPE_i++) \ + { \ + Ctype __DBUS_REPLY_BYTYPE_val; \ + \ + if (__DBUS_REPLY_BYTYPE_len == 1) \ + __DBUS_REPLY_BYTYPE_val = ((unsigned char *)__DBUS_REPLY_BYTYPE_blob)[__DBUS_REPLY_BYTYPE_i]; \ + else if (__DBUS_REPLY_BYTYPE_len == 2) \ + __DBUS_REPLY_BYTYPE_val = ((dbus_uint16_t *)__DBUS_REPLY_BYTYPE_blob)[__DBUS_REPLY_BYTYPE_i]; \ + else \ + __DBUS_REPLY_BYTYPE_val = ((dbus_uint32_t *)__DBUS_REPLY_BYTYPE_blob)[__DBUS_REPLY_BYTYPE_i]; \ + /*dbus_message_iter_append_basic (&__DBUS_REPLY_BYTYPE_sub, Dtype, __DBUS_REPLY_BYTYPE_val);*/ \ + dbus_message_iter_append_ ## Dappend (&__DBUS_REPLY_BYTYPE_sub, __DBUS_REPLY_BYTYPE_val); \ + } \ + } \ + } while (0) + +#define DBUS_REPLY_STRING(Dtype, Ctype) do { \ + int __DBUS_REPLY_BYTYPE_len; \ + \ + if (dhcp_interface_option_present (dhcp_iface, data->opt_id) \ + && ((__DBUS_REPLY_BYTYPE_len = dhcp_option_record_len (data->opt_id)) == 1) \ + && ((reply = dbus_message_new_method_return (message)) != NULL)) \ + { \ + Ctype __DBUS_REPLY_BYTYPE_val; \ + \ + __DBUS_REPLY_BYTYPE_val = (Ctype)dhcp_interface_option_payload (dhcp_iface, data->opt_id); \ + dbus_message_append_args (reply, Dtype, __DBUS_REPLY_BYTYPE_val, DBUS_TYPE_INVALID); \ + } \ + } while (0) + + +/* + * nm_dbus_dhcp_get_len + * + * Gets the total length of the specified DHCP option. + * + */ +static DBusMessage *nm_dbus_dhcp_get_len (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + if ((reply = dbus_message_new_method_return (message)) != NULL) + dbus_message_append_args (reply, DBUS_TYPE_UINT32, dhcp_interface_option_len (dhcp_iface, data->opt_id), DBUS_TYPE_INVALID); + + return reply; +} + +/* + * nm_dbus_dhcp_get_type + * + * Gets the type of the DHCP option. + * + */ +static DBusMessage *nm_dbus_dhcp_get_type (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + if ((reply = dbus_message_new_method_return (message)) != NULL) + { + if (nm_dbus_dhcp_record_type (data->opt_id) == DBUS_TYPE_STRING) + dbus_message_append_args (reply, DBUS_TYPE_UINT32, DBUS_TYPE_STRING, DBUS_TYPE_INVALID); + else if (dhcp_interface_option_len (dhcp_iface, data->opt_id) != dhcp_option_record_len (data->opt_id)) + dbus_message_append_args (reply, DBUS_TYPE_UINT32, DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); + else + dbus_message_append_args (reply, DBUS_TYPE_UINT32, nm_dbus_dhcp_record_type (data->opt_id), DBUS_TYPE_INVALID); + } + + return reply; +} + + +/* + * nm_dbus_dhcp_get_record_type + * + * Gets the length of individual records within the specified DHCP option. + * + */ +static DBusMessage *nm_dbus_dhcp_get_record_type (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + if ((reply = dbus_message_new_method_return (message)) != NULL) + dbus_message_append_args (reply, DBUS_TYPE_UINT32, nm_dbus_dhcp_record_type (data->opt_id), DBUS_TYPE_INVALID); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_boolean (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_BYTYPE (DBUS_TYPE_BOOLEAN, dbus_bool_t); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_booleanv (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_BYTYPEV (DBUS_TYPE_BOOLEAN, dbus_bool_t, boolean); + + return reply; +} + +static DBusMessage *nm_dbus_dhcp_get_byte (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_BYTYPE (DBUS_TYPE_BYTE, unsigned char); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_bytev (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_BYTYPEV (DBUS_TYPE_BYTE, unsigned char, byte); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_integer (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_BYTYPE (DBUS_TYPE_UINT32, dbus_uint32_t); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_integerv (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_BYTYPEV (DBUS_TYPE_UINT32, dbus_uint32_t, uint32); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_string (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + DBUS_REPLY_STRING (DBUS_TYPE_STRING, const char *); + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_generic (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + dhcp_iface = data->dhcp_iface; + + switch (nm_dbus_dhcp_record_type (data->opt_id)) + { + case DBUS_TYPE_BOOLEAN: + if (dhcp_interface_option_len (dhcp_iface, data->opt_id) == dhcp_option_record_len (data->opt_id)) + DBUS_REPLY_BYTYPE (DBUS_TYPE_BOOLEAN, dbus_bool_t); + else + DBUS_REPLY_BYTYPEV (DBUS_TYPE_BOOLEAN, dbus_bool_t, boolean); + break; + case DBUS_TYPE_BYTE: + if (dhcp_interface_option_len (dhcp_iface, data->opt_id) == dhcp_option_record_len (data->opt_id)) + DBUS_REPLY_BYTYPE (DBUS_TYPE_BYTE, unsigned char); + else + DBUS_REPLY_BYTYPEV (DBUS_TYPE_BYTE, unsigned char, byte); + break; + case DBUS_TYPE_UINT32: + if (dhcp_interface_option_len (dhcp_iface, data->opt_id) == dhcp_option_record_len (data->opt_id)) + DBUS_REPLY_BYTYPE(DBUS_TYPE_UINT32, dbus_uint32_t); + else + DBUS_REPLY_BYTYPEV (DBUS_TYPE_UINT32, dbus_uint32_t, uint32); + break; + case DBUS_TYPE_STRING: + DBUS_REPLY_STRING (DBUS_TYPE_STRING, const char *); + break; + } + + return reply; +} + + +static DBusMessage *nm_dbus_dhcp_get_name (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && (data->opt_id >= 0) && (data->dhcp_iface != NULL) && connection && message, NULL); + + if ((reply = dbus_message_new_method_return (message)) != NULL) + dbus_message_append_args (reply, DBUS_TYPE_STRING, dhcp_option_name (data->opt_id), DBUS_TYPE_INVALID); + + return reply; +} + + +/* + * nm_dbus_dhcp_validate + * + * Grab an option name or ID from the message and make sure its valid + * + */ +static DBusMessage *nm_dbus_dhcp_validate (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + DBusError error; + int id; + char *attribute = NULL; + gboolean success = FALSE; + NMDevice *dev; + struct dhcp_interface *dhcp_iface; + + g_return_val_if_fail (data && data->data && connection && message, NULL); + + /* Caller can ask for DHCP option by either name or ID. Try name first, then ID. */ + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &attribute, DBUS_TYPE_INVALID) || (attribute == NULL)) + { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_error_init (&error); + if (dbus_message_get_args (message, &error, DBUS_TYPE_UINT32, &id, DBUS_TYPE_INVALID) && (id >= 0)) + success = TRUE; + } + else if (isdigit (*attribute) && ((id = atoi (attribute)) == 0) && (*attribute != '0')) + { + /* If user passed a DHCP option name, find that option's ID */ + if ((id = dhcp_option_id_by_name (attribute)) != -1) + success = TRUE; + } + + if (success == TRUE) + { + if (!data->data->active_device || !(dhcp_iface = nm_device_get_dhcp_iface (data->data->active_device))) + { + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DhcpOptionsNotAvailable", + "DhcpOptions are not available at this time."); + success = FALSE; + } + else if (!dhcp_interface_option_present (dhcp_iface, id)) + { + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DhcpOptionNotPresent", + "The DhcpOption requested was not present."); + success = FALSE; + } + } + + if (success) + { + data->opt_id = id; + /* We're gonna need some locking here for dhcp_iface, right now we + * just hope it never goes away between the validate and the + * dispatch functions. ie, device gets deactivated, removed, etc. + */ + data->dhcp_iface = dhcp_iface; + } + else + { + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "OptionNotFound", + "The requested DHCP option does not exist."); + } + + return reply; +} + + +/* + * nm_dbus_dhcp_methods_setup + * + * Register handlers for dbus methods on the + * org.freedesktop.NetworkManager.DhcpOptions object. + * + */ +NMDbusMethodList *nm_dbus_dhcp_methods_setup (void) +{ + NMDbusMethodList *list = nm_dbus_method_list_new (nm_dbus_dhcp_validate); + + nm_dbus_method_list_add_method (list, "getLen", nm_dbus_dhcp_get_len); + nm_dbus_method_list_add_method (list, "getType", nm_dbus_dhcp_get_type); + nm_dbus_method_list_add_method (list, "getRecordType", nm_dbus_dhcp_get_record_type); + nm_dbus_method_list_add_method (list, "getBoolean", nm_dbus_dhcp_get_boolean); + nm_dbus_method_list_add_method (list, "getBooleanv", nm_dbus_dhcp_get_booleanv); + nm_dbus_method_list_add_method (list, "getByte", nm_dbus_dhcp_get_byte); + nm_dbus_method_list_add_method (list, "getBytev", nm_dbus_dhcp_get_bytev); + nm_dbus_method_list_add_method (list, "getBlob", nm_dbus_dhcp_get_bytev); /* getBlob is an alias for getBytev */ + nm_dbus_method_list_add_method (list, "getInteger", nm_dbus_dhcp_get_integer); + nm_dbus_method_list_add_method (list, "getIntegerv", nm_dbus_dhcp_get_integerv); + nm_dbus_method_list_add_method (list, "getString", nm_dbus_dhcp_get_string); + nm_dbus_method_list_add_method (list, "get", nm_dbus_dhcp_get_generic); + nm_dbus_method_list_add_method (list, "getName", nm_dbus_dhcp_get_name); + + return (list); +} diff --git a/src/nm-dbus-dhcp.h b/src/nm-dbus-dhcp.h new file mode 100644 index 0000000000..0f9066d15a --- /dev/null +++ b/src/nm-dbus-dhcp.h @@ -0,0 +1,29 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#ifndef NM_DBUS_DHCP_H +#define NM_DBUS_DHCP_H + +#include "NetworkManagerDbusUtils.h" + +NMDbusMethodList *nm_dbus_dhcp_methods_setup (void); + +#endif diff --git a/test/.cvsignore b/test/.cvsignore index 6be0a21d37..2e63101323 100644 --- a/test/.cvsignore +++ b/test/.cvsignore @@ -4,3 +4,4 @@ nminfotest nmtest nmtestdevices libnm_glib_test +nm-dhcp-opt-test diff --git a/test/Makefile.am b/test/Makefile.am index 36efd69d44..59a67c592f 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -8,9 +8,9 @@ AM_CPPFLAGS = \ -DBINDIR=\"$(bindir)\" \ -DDATADIR=\"$(datadir)\" -noinst_PROGRAMS = nmtest nminfotest nmtestdevices libnm_glib_test +noinst_PROGRAMS = nmtest nminfotest nmtestdevices libnm_glib_test nm-dhcp-opt-test -nmtest_SOURCES = nmclienttest.c +nmtest_SOURCES = nmtest.c nmtest_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) $(HAL_LIBS) nminfotest_SOURCES = nminfotest.c @@ -21,3 +21,6 @@ nmtestdevices_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) libnm_glib_test_SOURCES = libnm_glib_test.c libnm_glib_test_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) ../libnm_glib/libnm_glib.la + +nm_dhcp_opt_test_SOURCES = nm-dhcp-opt-test.c +nm_dhcp_opt_test_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) diff --git a/test/nm-dhcp-opt-test.c b/test/nm-dhcp-opt-test.c new file mode 100644 index 0000000000..732c0492fb --- /dev/null +++ b/test/nm-dhcp-opt-test.c @@ -0,0 +1,374 @@ +/* nm-dhcp-opt-test - test app for NetworkManager's DHCP Options interface + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "NetworkManager.h" + +/* Return codes for functions that use dbus */ +enum +{ + RETURN_SUCCESS = 1, + RETURN_FAILURE = 0, + RETURN_NO_NM = -1 +}; + + +#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist" +#define NM_DHCP_OPT_NOT_FOUND_ERROR "org.freedesktop.NetworkManager.OptionNotFound" + +static char *dbus_type_to_string (int type) +{ + switch (type) + { + case DBUS_TYPE_UINT32: + return "uint32"; + + case DBUS_TYPE_BOOLEAN: + return "boolean"; + + case DBUS_TYPE_BYTE: + return "byte"; + + case DBUS_TYPE_STRING: + return "string"; + } + g_assert_not_reached (); +} + + +gboolean get_one_arg (DBusMessage *message, int arg_type, int arg_type2, void **arg, int *item_count) +{ + gboolean success = FALSE; + + g_return_val_if_fail (message != NULL, FALSE); + g_return_val_if_fail (arg != NULL, FALSE); + + if (arg_type == DBUS_TYPE_ARRAY) + { + if (!item_count) + return FALSE; + success = dbus_message_get_args (message, NULL, DBUS_TYPE_ARRAY, arg_type2, + arg, item_count, DBUS_TYPE_INVALID); + } + else + { + switch (arg_type) + { + case DBUS_TYPE_STRING: + success = dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, arg, DBUS_TYPE_INVALID); + break; + case DBUS_TYPE_BYTE: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + case DBUS_TYPE_BOOLEAN: + success = dbus_message_get_args (message, NULL, arg_type, arg, DBUS_TYPE_INVALID); + break; + default: + fprintf (stderr, "get_one_arg (): Unknown argument type!\n"); + break; + } + } + return success; +} + + +/* + * call_nm_method + * + * Do a method call on NetworkManager. + * + * Returns: RETURN_SUCCESS on success + * RETURN_FAILURE on failure + * RETURN_NO_NM if NetworkManager service no longer exists + */ +static int call_nm_method (DBusConnection *con, const char *method, int opt, int arg_type, int arg_type2, void **arg, int *item_count) +{ + DBusMessage *message; + DBusMessage *reply; + DBusError error; + dbus_bool_t ret = TRUE; + DBusMessageIter iter; + + g_return_val_if_fail (con != NULL, RETURN_FAILURE); + g_return_val_if_fail (method != NULL, RETURN_FAILURE); + g_return_val_if_fail (arg != NULL, RETURN_FAILURE); + + if ((arg_type == DBUS_TYPE_STRING) || (arg_type2 == DBUS_TYPE_ARRAY)) + g_return_val_if_fail (*arg == NULL, RETURN_FAILURE); + + if (arg_type == DBUS_TYPE_ARRAY) + { + g_return_val_if_fail (item_count != NULL, RETURN_FAILURE); + *item_count = 0; + } + + if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH_DHCP, NM_DBUS_INTERFACE_DHCP, method))) + { + fprintf (stderr, "call_nm_method(): Couldn't allocate the dbus message\n"); + return (RETURN_FAILURE); + } + dbus_message_append_args (message, DBUS_TYPE_UINT32, opt, DBUS_TYPE_INVALID); + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, &error); + dbus_message_unref (message); + if (dbus_error_is_set (&error)) + { + int ret = RETURN_FAILURE; + + if (!strcmp (error.name, DBUS_NO_SERVICE_ERROR)) + ret = RETURN_NO_NM; + + if (ret != RETURN_SUCCESS && (strcmp (error.name, NM_DHCP_OPT_NOT_FOUND_ERROR) != 0)) + fprintf (stderr, "call_nm_method(): %s raised:\n %s\n\n", error.name, error.message); + + dbus_error_free (&error); + return (ret); + } + + if (reply == NULL) + { + fprintf (stderr, "call_nm_method(): dbus reply message was NULL\n" ); + return (RETURN_FAILURE); + } + + ret = get_one_arg (reply, arg_type, arg_type2, arg, item_count); + dbus_message_unref (reply); + if (!ret) + { + fprintf (stderr, "call_nm_method(): error while getting args: name='%s' message='%s'\n", error.name, error.message); + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + return (RETURN_FAILURE); + } + + return (RETURN_SUCCESS); +} + + +int get_opt_type (DBusConnection *connection, int opt, gboolean record) +{ + int ret; + int type = -1; + + ret = call_nm_method (connection, record ? "getRecordType" : "getType", opt, DBUS_TYPE_UINT32, DBUS_TYPE_INVALID, (void *)(&type), NULL); + if (ret == RETURN_SUCCESS) + return (type); + + return (-1); +} + + +void print_array (DBusConnection *connection, int opt, int opt_type) +{ + int num_items; + unsigned int *uint32 = NULL; + int *int32 = NULL; + gboolean *bool = NULL; + unsigned char *byte = NULL; + void *item; + char *method; + int ret; + const char *name = NULL; + + switch (opt_type) + { + case DBUS_TYPE_UINT32: + item = &uint32; + method = "getIntegerv"; + break; + + case DBUS_TYPE_BOOLEAN: + item = &bool; + method = "getBooleanv"; + break; + + case DBUS_TYPE_BYTE: + item = &byte; + method = "getBytev"; + break; + + default: + fprintf (stderr, "%d: Type %c\n", opt, opt_type); + g_assert_not_reached (); + break; + } + + ret = call_nm_method (connection, "getName", opt, DBUS_TYPE_STRING, DBUS_TYPE_INVALID, (void *)(&name), NULL); + if (ret != RETURN_SUCCESS) + name = NULL; + + ret = call_nm_method (connection, method, opt, DBUS_TYPE_ARRAY, opt_type, item, &num_items); + if ((ret == RETURN_SUCCESS) && (num_items > 0)) + { + int i; + fprintf (stderr, "%d ('%s'): (%d records of type %s) ", opt, name, num_items, dbus_type_to_string (opt_type)); + for (i = 0; i < num_items; i++) + { + switch (opt_type) + { + case DBUS_TYPE_BYTE: + fprintf (stderr, "%d, ", byte[i]); + break; + case DBUS_TYPE_BOOLEAN: + fprintf (stderr, "%d, ", bool[i]); + break; + case DBUS_TYPE_UINT32: + fprintf (stderr, "%u, ", uint32[i]); + break; + + default: + g_assert_not_reached (); + break; + } + } + fprintf (stderr, "\n"); + } +} + +void print_one_item (DBusConnection *connection, int opt, int opt_type) +{ + unsigned int uint32; + int int32; + gboolean bool; + unsigned char byte; + char *string = NULL; + void *item = NULL; + char *method; + int ret; + const char *name = NULL; + + switch (opt_type) + { + case DBUS_TYPE_UINT32: + item = &uint32; + method = "getInteger"; + break; + + case DBUS_TYPE_BOOLEAN: + item = &bool; + method = "getBoolean"; + break; + + case DBUS_TYPE_BYTE: + item = &byte; + method = "getByte"; + break; + + case DBUS_TYPE_STRING: + item = &string; + method = "getString"; + break; + + default: + fprintf (stderr, "%d: Type %c\n", opt, opt_type); + g_assert_not_reached (); + break; + } + + ret = call_nm_method (connection, "getName", opt, DBUS_TYPE_STRING, DBUS_TYPE_INVALID, (void *)(&name), NULL); + if (ret != RETURN_SUCCESS) + name = NULL; + + ret = call_nm_method (connection, method, opt, opt_type, DBUS_TYPE_INVALID, item, NULL); + if (ret == RETURN_SUCCESS) + { + fprintf (stderr, "%d ('%s'): (%s) ", opt, name, dbus_type_to_string (opt_type)); + switch (opt_type) + { + case DBUS_TYPE_BYTE: + fprintf (stderr, "%d\n", byte); + break; + case DBUS_TYPE_BOOLEAN: + fprintf (stderr, "%d\n", bool); + break; + case DBUS_TYPE_UINT32: + fprintf (stderr, "%u\n", uint32); + break; + case DBUS_TYPE_STRING: + fprintf (stderr, "'%s'\n", string); + break; + + default: + g_assert_not_reached (); + break; + } + } +} + + +void print_each_dhcp_option (DBusConnection *connection) +{ + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusError error; + int i; + int opt_type; + int ret; + + g_return_if_fail (connection != NULL); + + /* Loop through all available DHCP options and print each one. */ + for (i = 1; i < 62; i++) + { + int opt_type = get_opt_type (connection, i, FALSE); + + if (opt_type == DBUS_TYPE_ARRAY) + { + int opt_type2; + + /* get the array item type */ + opt_type2 = get_opt_type (connection, i, TRUE); + print_array (connection, i, opt_type2); + } + else if (opt_type != -1) + print_one_item (connection, i, opt_type); + } +} + + +int main (int argc, char **argv) +{ + DBusConnection *connection; + DBusError error; + + g_type_init (); + + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (connection == NULL) + { + fprintf (stderr, "Error connecting to system bus: %s\n", error.message); + dbus_error_free (&error); + return 1; + } + + print_each_dhcp_option (connection); + + exit (0); +}