device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-util / nm-setting-wired.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
3 /*
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301 USA.
18  *
19  * Copyright 2007 - 2014 Red Hat, Inc.
20  * Copyright 2007 - 2008 Novell, Inc.
21  */
22
23 #include "nm-default.h"
24
25 #include <string.h>
26 #include <net/ethernet.h>
27 #include <netinet/ether.h>
28 #include <dbus/dbus-glib.h>
29
30 #include "nm-setting-wired.h"
31 #include "nm-param-spec-specialized.h"
32 #include "nm-utils.h"
33 #include "nm-utils-private.h"
34 #include "nm-dbus-glib-types.h"
35 #include "nm-setting-private.h"
36
37 /**
38  * SECTION:nm-setting-wired
39  * @short_description: Describes connection properties for Ethernet-based networks
40  * @include: nm-setting-wired.h
41  *
42  * The #NMSettingWired object is a #NMSetting subclass that describes properties
43  * necessary for connection to Ethernet networks.
44  **/
45
46 /**
47  * nm_setting_wired_error_quark:
48  *
49  * Registers an error quark for #NMSettingWired if necessary.
50  *
51  * Returns: the error quark used for #NMSettingWired errors.
52  **/
53 GQuark
54 nm_setting_wired_error_quark (void)
55 {
56         static GQuark quark;
57
58         if (G_UNLIKELY (!quark))
59                 quark = g_quark_from_static_string ("nm-setting-wired-error-quark");
60         return quark;
61 }
62
63
64 G_DEFINE_TYPE_WITH_CODE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING,
65                          _nm_register_setting (NM_SETTING_WIRED_SETTING_NAME,
66                                                g_define_type_id,
67                                                1,
68                                                NM_SETTING_WIRED_ERROR))
69 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRED)
70
71 #define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate))
72
73 typedef struct {
74         char *port;
75         guint32 speed;
76         char *duplex;
77         gboolean auto_negotiate;
78         GByteArray *device_mac_address;
79         GByteArray *cloned_mac_address;
80         GSList *mac_address_blacklist;
81         guint32 mtu;
82         GPtrArray *s390_subchannels;
83         char *s390_nettype;
84         GHashTable *s390_options;
85 } NMSettingWiredPrivate;
86
87 enum {
88         PROP_0,
89         PROP_PORT,
90         PROP_SPEED,
91         PROP_DUPLEX,
92         PROP_AUTO_NEGOTIATE,
93         PROP_MAC_ADDRESS,
94         PROP_CLONED_MAC_ADDRESS,
95         PROP_MAC_ADDRESS_BLACKLIST,
96         PROP_MTU,
97         PROP_S390_SUBCHANNELS,
98         PROP_S390_NETTYPE,
99         PROP_S390_OPTIONS,
100
101         LAST_PROP
102 };
103
104 static const char *valid_s390_opts[] = {
105         "portno", "layer2", "portname", "protocol", "priority_queueing",
106         "buffer_count", "isolation", "total", "inter", "inter_jumbo", "route4",
107         "route6", "fake_broadcast", "broadcast_mode", "canonical_macaddr",
108         "checksumming", "sniffer", "large_send", "ipato_enable", "ipato_invert4",
109         "ipato_add4", "ipato_invert6", "ipato_add6", "vipa_add4", "vipa_add6",
110         "rxip_add4", "rxip_add6", "lancmd_timeout", "ctcprot",
111         NULL
112 };
113
114 /**
115  * nm_setting_wired_new:
116  *
117  * Creates a new #NMSettingWired object with default values.
118  *
119  * Returns: (transfer full): the new empty #NMSettingWired object
120  **/
121 NMSetting *
122 nm_setting_wired_new (void)
123 {
124         return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRED, NULL);
125 }
126
127 /**
128  * nm_setting_wired_get_port:
129  * @setting: the #NMSettingWired
130  *
131  * Returns: the #NMSettingWired:port property of the setting
132  **/
133 const char *
134 nm_setting_wired_get_port (NMSettingWired *setting)
135 {
136         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
137
138         return NM_SETTING_WIRED_GET_PRIVATE (setting)->port;
139 }
140
141 /**
142  * nm_setting_wired_get_speed:
143  * @setting: the #NMSettingWired
144  *
145  * Returns: the #NMSettingWired:speed property of the setting
146  **/
147 guint32
148 nm_setting_wired_get_speed (NMSettingWired *setting)
149 {
150         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
151
152         return NM_SETTING_WIRED_GET_PRIVATE (setting)->speed;
153 }
154
155 /**
156  * nm_setting_wired_get_duplex:
157  * @setting: the #NMSettingWired
158  *
159  * Returns: the #NMSettingWired:duplex property of the setting
160  **/
161 const char *
162 nm_setting_wired_get_duplex (NMSettingWired *setting)
163 {
164         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
165
166         return NM_SETTING_WIRED_GET_PRIVATE (setting)->duplex;
167 }
168
169 /**
170  * nm_setting_wired_get_auto_negotiate:
171  * @setting: the #NMSettingWired
172  *
173  * Returns: the #NMSettingWired:auto-negotiate property of the setting
174  **/
175 gboolean
176 nm_setting_wired_get_auto_negotiate (NMSettingWired *setting)
177 {
178         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
179
180         return NM_SETTING_WIRED_GET_PRIVATE (setting)->auto_negotiate;
181 }
182
183 /**
184  * nm_setting_wired_get_mac_address:
185  * @setting: the #NMSettingWired
186  *
187  * Returns: the #NMSettingWired:mac-address property of the setting
188  **/
189 const GByteArray *
190 nm_setting_wired_get_mac_address (NMSettingWired *setting)
191 {
192         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
193
194         return NM_SETTING_WIRED_GET_PRIVATE (setting)->device_mac_address;
195 }
196
197 /**
198  * nm_setting_wired_get_cloned_mac_address:
199  * @setting: the #NMSettingWired
200  *
201  * Returns: the #NMSettingWired:cloned-mac-address property of the setting
202  **/
203 const GByteArray *
204 nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting)
205 {
206         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
207
208         return NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address;
209 }
210
211 /**
212  * nm_setting_wired_get_mac_address_blacklist:
213  * @setting: the #NMSettingWired
214  *
215  * Returns: (element-type GLib.ByteArray): the #NMSettingWired:mac-address-blacklist
216  * property of the setting
217  **/
218 const GSList *
219 nm_setting_wired_get_mac_address_blacklist (NMSettingWired *setting)
220 {
221         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
222
223         return NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist;
224 }
225
226 /**
227  * nm_setting_wired_get_num_mac_blacklist_items:
228  * @setting: the #NMSettingWired
229  *
230  * Returns: the number of blacklisted MAC addresses
231  *
232  * Since: 0.9.10
233  **/
234 guint32
235 nm_setting_wired_get_num_mac_blacklist_items (NMSettingWired *setting)
236 {
237         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
238
239         return g_slist_length (NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist);
240 }
241
242 /**
243  * nm_setting_wired_get_mac_blacklist_item:
244  * @setting: the #NMSettingWired
245  * @idx: the zero-based index of the MAC address entry
246  *
247  * Returns: the blacklisted MAC address string (hex-digits-and-colons notation)
248  * at index @idx
249  *
250  * Since: 0.9.10
251  **/
252 const char *
253 nm_setting_wired_get_mac_blacklist_item (NMSettingWired *setting, guint32 idx)
254 {
255         NMSettingWiredPrivate *priv;
256
257         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
258
259         priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
260         g_return_val_if_fail (idx <= g_slist_length (priv->mac_address_blacklist), NULL);
261
262         return (const char *) g_slist_nth_data (priv->mac_address_blacklist, idx);
263 }
264
265 /**
266  * nm_setting_wired_add_mac_blacklist_item:
267  * @setting: the #NMSettingWired
268  * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist
269  *
270  * Adds a new MAC address to the #NMSettingWired:mac-address-blacklist property.
271  *
272  * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address
273  * is invalid or was already present
274  *
275  * Since: 0.9.10
276  **/
277 gboolean
278 nm_setting_wired_add_mac_blacklist_item (NMSettingWired *setting, const char *mac)
279 {
280         NMSettingWiredPrivate *priv;
281         GSList *iter;
282         guint8 buf[32];
283
284         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
285         g_return_val_if_fail (mac != NULL, FALSE);
286
287         if (!nm_utils_hwaddr_aton (mac, ARPHRD_ETHER, buf))
288                 return FALSE;
289
290         priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
291         for (iter = priv->mac_address_blacklist; iter; iter = g_slist_next (iter)) {
292                 if (!strcasecmp (mac, (char *) iter->data))
293                         return FALSE;
294         }
295
296         priv->mac_address_blacklist = g_slist_append (priv->mac_address_blacklist,
297                                                       g_ascii_strup (mac, -1));
298         g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
299         return TRUE;
300 }
301
302 /**
303  * nm_setting_wired_remove_mac_blacklist_item:
304  * @setting: the #NMSettingWired
305  * @idx: index number of the MAC address
306  *
307  * Removes the MAC address at index @idx from the blacklist.
308  *
309  * Since: 0.9.10
310  **/
311 void
312 nm_setting_wired_remove_mac_blacklist_item (NMSettingWired *setting, guint32 idx)
313 {
314         NMSettingWiredPrivate *priv;
315         GSList *elt;
316
317         g_return_if_fail (NM_IS_SETTING_WIRED (setting));
318
319         priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
320         elt = g_slist_nth (priv->mac_address_blacklist, idx);
321         g_return_if_fail (elt != NULL);
322
323         g_free (elt->data);
324         priv->mac_address_blacklist = g_slist_delete_link (priv->mac_address_blacklist, elt);
325         g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
326 }
327
328 /**
329  * nm_setting_wired_remove_mac_blacklist_item_by_value:
330  * @setting: the #NMSettingWired
331  * @mac: the MAC address string (hex-digits-and-colons notation) to remove from
332  * the blacklist
333  *
334  * Removes the MAC address @mac from the blacklist.
335  *
336  * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not.
337  *
338  * Since: 0.9.10
339  **/
340 gboolean
341 nm_setting_wired_remove_mac_blacklist_item_by_value (NMSettingWired *setting, const char *mac)
342 {
343         NMSettingWiredPrivate *priv;
344         GSList *iter;
345         guint8 buf[32];
346
347         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
348         g_return_val_if_fail (mac != NULL, FALSE);
349
350         if (!nm_utils_hwaddr_aton (mac, ARPHRD_ETHER, buf))
351                 return FALSE;
352
353         priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
354         for (iter = priv->mac_address_blacklist; iter; iter = g_slist_next (iter)) {
355                 if (!strcasecmp (mac, (char *) iter->data)) {
356                         priv->mac_address_blacklist = g_slist_delete_link (priv->mac_address_blacklist, iter);
357                         g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
358                         return TRUE;
359                 }
360         }
361         return FALSE;
362 }
363
364 /**
365  * nm_setting_wired_clear_mac_blacklist_items:
366  * @setting: the #NMSettingWired
367  *
368  * Removes all blacklisted MAC addresses.
369  *
370  * Since: 0.9.10
371  **/
372 void
373 nm_setting_wired_clear_mac_blacklist_items (NMSettingWired *setting)
374 {
375         g_return_if_fail (NM_IS_SETTING_WIRED (setting));
376
377         g_slist_free_full (NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist, g_free);
378         NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist = NULL;
379         g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
380 }
381
382 /**
383  * nm_setting_wired_get_mtu:
384  * @setting: the #NMSettingWired
385  *
386  * Returns: the #NMSettingWired:mtu property of the setting
387  **/
388 guint32
389 nm_setting_wired_get_mtu (NMSettingWired *setting)
390 {
391         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
392
393         return NM_SETTING_WIRED_GET_PRIVATE (setting)->mtu;
394 }
395
396 /**
397  * nm_setting_wired_get_s390_subchannels:
398  * @setting: the #NMSettingWired
399  *
400  * Return the list of s390 subchannels that identify the device that this
401  * connection is applicable to.  The connection should only be used in
402  * conjunction with that device.
403  *
404  * Returns: (element-type utf8): #GPtrArray of strings, each specifying one
405  * subchannel the s390 device uses to communicate to the host.
406  **/
407 const GPtrArray *
408 nm_setting_wired_get_s390_subchannels (NMSettingWired *setting)
409 {
410         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
411
412         return NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_subchannels;
413 }
414
415 /**
416  * nm_setting_wired_get_s390_nettype:
417  * @setting: the #NMSettingWired
418  *
419  * Returns the s390 device type this connection should apply to.  Will be one
420  * of 'qeth', 'lcs', or 'ctc'.
421  *
422  * Returns: the s390 device type
423  **/
424 const char *
425 nm_setting_wired_get_s390_nettype (NMSettingWired *setting)
426 {
427         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
428
429         return NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_nettype;
430 }
431
432 /**
433  * nm_setting_wired_get_num_s390_options:
434  * @setting: the #NMSettingWired
435  *
436  * Returns the number of s390-specific options that should be set for this
437  * device when it is activated.  This can be used to retrieve each s390
438  * option individually using nm_setting_wired_get_s390_option().
439  *
440  * Returns: the number of s390-specific device options
441  **/
442 guint32
443 nm_setting_wired_get_num_s390_options (NMSettingWired *setting)
444 {
445         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
446
447         return g_hash_table_size (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options);
448 }
449
450 /**
451  * nm_setting_wired_get_s390_option:
452  * @setting: the #NMSettingWired
453  * @idx: index of the desired option, from 0 to
454  * nm_setting_wired_get_num_s390_options() - 1
455  * @out_key: (out): on return, the key name of the s390 specific option; this
456  * value is owned by the setting and should not be modified
457  * @out_value: (out): on return, the value of the key of the s390 specific
458  * option; this value is owned by the setting and should not be modified
459  *
460  * Given an index, return the value of the s390 option at that index.  indexes
461  * are *not* guaranteed to be static across modifications to options done by
462  * nm_setting_wired_add_s390_option() and nm_setting_wired_remove_s390_option(),
463  * and should not be used to refer to options except for short periods of time
464  * such as during option iteration.
465  *
466  * Returns: %TRUE on success if the index was valid and an option was found,
467  * %FALSE if the index was invalid (ie, greater than the number of options
468  * currently held by the setting)
469  **/
470 gboolean
471 nm_setting_wired_get_s390_option (NMSettingWired *setting,
472                                   guint32 idx,
473                                   const char **out_key,
474                                   const char **out_value)
475 {
476         const char *_key, *_value;
477         GHashTableIter iter;
478         guint i = 0;
479
480         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
481
482         g_hash_table_iter_init (&iter, NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options);
483         while (g_hash_table_iter_next (&iter, (gpointer) &_key, (gpointer) &_value)) {
484                 if (i == idx) {
485                         if (out_key)
486                                 *out_key = _key;
487                         if (out_value)
488                                 *out_value = _value;
489                         return TRUE;
490                 }
491                 i++;
492         }
493         g_return_val_if_reached (FALSE);
494 }
495
496 /**
497  * nm_setting_wired_get_s390_option_by_key:
498  * @setting: the #NMSettingWired
499  * @key: the key for which to retrieve the value
500  *
501  * Returns the value associated with the s390-specific option specified by
502  * @key, if it exists.
503  *
504  * Returns: the value, or %NULL if the key/value pair was never added to the
505  * setting; the value is owned by the setting and must not be modified
506  **/
507 const char *
508 nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting,
509                                          const char *key)
510 {
511         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
512         g_return_val_if_fail (key != NULL, NULL);
513         g_return_val_if_fail (strlen (key), NULL);
514
515         return g_hash_table_lookup (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key);
516 }
517
518 /**
519  * nm_setting_wired_add_s390_option:
520  * @setting: the #NMSettingWired
521  * @key: key name for the option
522  * @value: value for the option
523  *
524  * Add an option to the table.  The option is compared to an internal list
525  * of allowed options.  Key names may contain only alphanumeric characters
526  * (ie [a-zA-Z0-9]).  Adding a new key replaces any existing key/value pair that
527  * may already exist.
528  *
529  * Returns: %TRUE if the option was valid and was added to the internal option
530  * list, %FALSE if it was not.
531  **/
532 gboolean
533 nm_setting_wired_add_s390_option (NMSettingWired *setting,
534                                   const char *key,
535                                   const char *value)
536 {
537         size_t value_len;
538
539         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
540         g_return_val_if_fail (key != NULL, FALSE);
541         g_return_val_if_fail (strlen (key), FALSE);
542         g_return_val_if_fail (_nm_utils_string_in_list (key, valid_s390_opts), FALSE);
543         g_return_val_if_fail (value != NULL, FALSE);
544
545         value_len = strlen (value);
546         g_return_val_if_fail (value_len > 0 && value_len < 200, FALSE);
547
548         g_hash_table_insert (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options,
549                              g_strdup (key),
550                              g_strdup (value));
551         g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_S390_OPTIONS);
552         return TRUE;
553 }
554
555 /**
556  * nm_setting_wired_remove_s390_option:
557  * @setting: the #NMSettingWired
558  * @key: key name for the option to remove
559  *
560  * Remove the s390-specific option referenced by @key from the internal option
561  * list.
562  *
563  * Returns: %TRUE if the option was found and removed from the internal option
564  * list, %FALSE if it was not.
565  **/
566 gboolean
567 nm_setting_wired_remove_s390_option (NMSettingWired *setting,
568                                      const char *key)
569 {
570         gboolean found;
571
572         g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
573         g_return_val_if_fail (key != NULL, FALSE);
574         g_return_val_if_fail (strlen (key), FALSE);
575
576         found = g_hash_table_remove (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key);
577         if (found)
578                 g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_S390_OPTIONS);
579         return found;
580 }
581
582 /**
583  * nm_setting_wired_get_valid_s390_options:
584  * @setting: the #NMSettingWired
585  *
586  * Returns a list of valid s390 options.
587  *
588  * Returns: (transfer none): a %NULL-terminated array of strings of valid s390 options.
589  *
590  * Since: 0.9.10
591  **/
592 const char **
593 nm_setting_wired_get_valid_s390_options (NMSettingWired *setting)
594 {
595         return valid_s390_opts;
596 }
597
598 static gboolean
599 verify (NMSetting *setting, GSList *all_settings, GError **error)
600 {
601         NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
602         const char *valid_ports[] = { "tp", "aui", "bnc", "mii", NULL };
603         const char *valid_duplex[] = { "half", "full", NULL };
604         const char *valid_nettype[] = { "qeth", "lcs", "ctc", NULL };
605         GHashTableIter iter;
606         GSList* mac_blacklist_iter;
607         const char *key, *value;
608
609         if (priv->port && !_nm_utils_string_in_list (priv->port, valid_ports)) {
610                 g_set_error (error,
611                              NM_SETTING_WIRED_ERROR,
612                              NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
613                              _("'%s' is not a valid Ethernet port value"),
614                              priv->port);
615                 g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_PORT);
616                 return FALSE;
617         }
618
619         if (priv->duplex && !_nm_utils_string_in_list (priv->duplex, valid_duplex)) {
620                 g_set_error (error,
621                              NM_SETTING_WIRED_ERROR,
622                              NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
623                              _("'%s' is not a valid duplex value"),
624                              priv->duplex);
625                 g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX);
626                 return FALSE;
627         }
628
629         if (priv->device_mac_address && priv->device_mac_address->len != ETH_ALEN) {
630                 g_set_error_literal (error,
631                                      NM_SETTING_WIRED_ERROR,
632                                      NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
633                                      _("is not a valid MAC address"));
634                 g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS);
635                 return FALSE;
636         }
637
638         for (mac_blacklist_iter = priv->mac_address_blacklist; mac_blacklist_iter;
639              mac_blacklist_iter = mac_blacklist_iter->next) {
640                 struct ether_addr addr;
641
642                 if (!ether_aton_r (mac_blacklist_iter->data, &addr)) {
643                         g_set_error (error,
644                                      NM_SETTING_WIRED_ERROR,
645                                      NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
646                                      _("'%s' is not a valid MAC address"),
647                                      (const char *) mac_blacklist_iter->data);
648                         g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
649                         return FALSE;
650                 }
651         }
652
653         if (   priv->s390_subchannels
654             && !(priv->s390_subchannels->len == 3 || priv->s390_subchannels->len == 2)) {
655                 g_set_error_literal (error,
656                                      NM_SETTING_WIRED_ERROR,
657                                      NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
658                                      _("property is invalid"));
659                 g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_SUBCHANNELS);
660                 return FALSE;
661         }
662
663         if (priv->s390_nettype && !_nm_utils_string_in_list (priv->s390_nettype, valid_nettype)) {
664                 g_set_error_literal (error,
665                                      NM_SETTING_WIRED_ERROR,
666                                      NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
667                                      _("property is invalid"));
668                 g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_NETTYPE);
669                 return FALSE;
670         }
671
672         g_hash_table_iter_init (&iter, priv->s390_options);
673         while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
674                 if (   !_nm_utils_string_in_list (key, valid_s390_opts)
675                     || !strlen (value)
676                     || (strlen (value) > 200)) {
677                         g_set_error (error,
678                                      NM_SETTING_WIRED_ERROR,
679                                      NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
680                                      _("invalid '%s' or its value '%s'"),
681                                      key, value);
682                         g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_OPTIONS);
683                         return FALSE;
684                 }
685         }
686
687         if (priv->cloned_mac_address && priv->cloned_mac_address->len != ETH_ALEN) {
688                 g_set_error_literal (error,
689                                      NM_SETTING_WIRED_ERROR,
690                                      NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
691                                      _("is not a valid MAC address"));
692                 g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
693                 return FALSE;
694         }
695
696         return TRUE;
697 }
698
699 static void
700 nm_setting_wired_init (NMSettingWired *setting)
701 {
702         NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
703
704         priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
705 }
706
707 static void
708 finalize (GObject *object)
709 {
710         NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object);
711
712         g_free (priv->port);
713         g_free (priv->duplex);
714         g_free (priv->s390_nettype);
715
716         g_hash_table_destroy (priv->s390_options);
717
718         if (priv->device_mac_address)
719                 g_byte_array_free (priv->device_mac_address, TRUE);
720
721         if (priv->cloned_mac_address)
722                 g_byte_array_free (priv->cloned_mac_address, TRUE);
723
724         g_slist_free_full (priv->mac_address_blacklist, g_free);
725
726         if (priv->s390_subchannels) {
727                 g_ptr_array_set_free_func (priv->s390_subchannels, g_free);
728                 g_ptr_array_free (priv->s390_subchannels, TRUE);
729         }
730
731         G_OBJECT_CLASS (nm_setting_wired_parent_class)->finalize (object);
732 }
733
734 static void
735 copy_hash (gpointer key, gpointer value, gpointer user_data)
736 {
737         g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), g_strdup (value));
738 }
739
740 static void
741 set_property (GObject *object, guint prop_id,
742               const GValue *value, GParamSpec *pspec)
743 {
744         NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object);
745         GHashTable *new_hash;
746
747         switch (prop_id) {
748         case PROP_PORT:
749                 g_free (priv->port);
750                 priv->port = g_value_dup_string (value);
751                 break;
752         case PROP_SPEED:
753                 priv->speed = g_value_get_uint (value);
754                 break;
755         case PROP_DUPLEX:
756                 g_free (priv->duplex);
757                 priv->duplex = g_value_dup_string (value);
758                 break;
759         case PROP_AUTO_NEGOTIATE:
760                 priv->auto_negotiate = g_value_get_boolean (value);
761                 break;
762         case PROP_MAC_ADDRESS:
763                 if (priv->device_mac_address)
764                         g_byte_array_free (priv->device_mac_address, TRUE);
765                 priv->device_mac_address = g_value_dup_boxed (value);
766                 break;
767         case PROP_CLONED_MAC_ADDRESS:
768                 if (priv->cloned_mac_address)
769                         g_byte_array_free (priv->cloned_mac_address, TRUE);
770                 priv->cloned_mac_address = g_value_dup_boxed (value);
771                 break;
772         case PROP_MAC_ADDRESS_BLACKLIST:
773                 g_slist_free_full (priv->mac_address_blacklist, g_free);
774                 priv->mac_address_blacklist = g_value_dup_boxed (value);
775                 break;
776         case PROP_MTU:
777                 priv->mtu = g_value_get_uint (value);
778                 break;
779         case PROP_S390_SUBCHANNELS:
780                 if (priv->s390_subchannels) {
781                         g_ptr_array_set_free_func (priv->s390_subchannels, g_free);
782                         g_ptr_array_free (priv->s390_subchannels, TRUE);
783                 }
784                 priv->s390_subchannels = g_value_dup_boxed (value);
785                 break;
786         case PROP_S390_NETTYPE:
787                 g_free (priv->s390_nettype);
788                 priv->s390_nettype = g_value_dup_string (value);
789                 break;
790         case PROP_S390_OPTIONS:
791                 /* Must make a deep copy of the hash table here... */
792                 g_hash_table_remove_all (priv->s390_options);
793                 new_hash = g_value_get_boxed (value);
794                 if (new_hash)
795                         g_hash_table_foreach (new_hash, copy_hash, priv->s390_options);
796                 break;
797         default:
798                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
799                 break;
800         }
801 }
802
803 static void
804 get_property (GObject *object, guint prop_id,
805               GValue *value, GParamSpec *pspec)
806 {
807         NMSettingWired *setting = NM_SETTING_WIRED (object);
808         NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
809
810         switch (prop_id) {
811         case PROP_PORT:
812                 g_value_set_string (value, nm_setting_wired_get_port (setting));
813                 break;
814         case PROP_SPEED:
815                 g_value_set_uint (value, nm_setting_wired_get_speed (setting));
816                 break;
817         case PROP_DUPLEX:
818                 g_value_set_string (value, nm_setting_wired_get_duplex (setting));
819                 break;
820         case PROP_AUTO_NEGOTIATE:
821                 g_value_set_boolean (value, nm_setting_wired_get_auto_negotiate (setting));
822                 break;
823         case PROP_MAC_ADDRESS:
824                 g_value_set_boxed (value, nm_setting_wired_get_mac_address (setting));
825                 break;
826         case PROP_CLONED_MAC_ADDRESS:
827                 g_value_set_boxed (value, nm_setting_wired_get_cloned_mac_address (setting));
828                 break;
829         case PROP_MAC_ADDRESS_BLACKLIST:
830                 g_value_set_boxed (value, nm_setting_wired_get_mac_address_blacklist (setting));
831                 break;
832         case PROP_MTU:
833                 g_value_set_uint (value, nm_setting_wired_get_mtu (setting));
834                 break;
835         case PROP_S390_SUBCHANNELS:
836                 g_value_set_boxed (value, nm_setting_wired_get_s390_subchannels (setting));
837                 break;
838         case PROP_S390_NETTYPE:
839                 g_value_set_string (value, nm_setting_wired_get_s390_nettype (setting));
840                 break;
841         case PROP_S390_OPTIONS:
842                 g_value_set_boxed (value, priv->s390_options);
843                 break;
844         default:
845                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
846                 break;
847         }
848 }
849
850 static void
851 nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
852 {
853         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
854         NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
855
856         g_type_class_add_private (setting_class, sizeof (NMSettingWiredPrivate));
857
858         /* virtual methods */
859         object_class->set_property = set_property;
860         object_class->get_property = get_property;
861         object_class->finalize     = finalize;
862         parent_class->verify       = verify;
863
864         /* Properties */
865         /**
866          * NMSettingWired:port:
867          *
868          * Specific port type to use if multiple the device supports multiple
869          * attachment methods.  One of "tp" (Twisted Pair), "aui" (Attachment Unit
870          * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface.
871          * If the device supports only one port type, this setting is ignored.
872          **/
873         g_object_class_install_property
874                 (object_class, PROP_PORT,
875                  g_param_spec_string (NM_SETTING_WIRED_PORT, "", "",
876                                       NULL,
877                                       G_PARAM_READWRITE |
878                                       G_PARAM_STATIC_STRINGS));
879
880         /**
881          * NMSettingWired:speed:
882          *
883          * If non-zero, request that the device use only the specified speed.  In
884          * Mbit/s, ie 100 == 100Mbit/s.
885          **/
886         g_object_class_install_property
887                 (object_class, PROP_SPEED,
888                  g_param_spec_uint (NM_SETTING_WIRED_SPEED, "", "",
889                                     0, G_MAXUINT32, 0,
890                                     G_PARAM_READWRITE |
891                                     G_PARAM_CONSTRUCT |
892                                     G_PARAM_STATIC_STRINGS));
893
894         /**
895          * NMSettingWired:duplex:
896          *
897          * If specified, request that the device only use the specified duplex mode.
898          * Either "half" or "full".
899          **/
900         g_object_class_install_property
901                 (object_class, PROP_DUPLEX,
902                  g_param_spec_string (NM_SETTING_WIRED_DUPLEX, "", "",
903                                       NULL,
904                                       G_PARAM_READWRITE |
905                                       G_PARAM_STATIC_STRINGS));
906
907         /**
908          * NMSettingWired:auto-negotiate:
909          *
910          * If %TRUE, allow auto-negotiation of port speed and duplex mode.  If
911          * %FALSE, do not allow auto-negotiation, in which case the "speed" and
912          * "duplex" properties should be set.
913          **/
914         g_object_class_install_property
915                 (object_class, PROP_AUTO_NEGOTIATE,
916                  g_param_spec_boolean (NM_SETTING_WIRED_AUTO_NEGOTIATE, "", "",
917                                        TRUE,
918                                        G_PARAM_READWRITE |
919                                        G_PARAM_CONSTRUCT |
920                                        G_PARAM_STATIC_STRINGS));
921
922         /**
923          * NMSettingWired:mac-address:
924          *
925          * If specified, this connection will only apply to the Ethernet device
926          * whose permanent MAC address matches. This property does not change the
927          * MAC address of the device (i.e. MAC spoofing).
928          **/
929         g_object_class_install_property
930                 (object_class, PROP_MAC_ADDRESS,
931                  _nm_param_spec_specialized (NM_SETTING_WIRED_MAC_ADDRESS, "", "",
932                                              DBUS_TYPE_G_UCHAR_ARRAY,
933                                              G_PARAM_READWRITE |
934                                              NM_SETTING_PARAM_INFERRABLE |
935                                              G_PARAM_STATIC_STRINGS));
936
937         /**
938          * NMSettingWired:cloned-mac-address:
939          *
940          * If specified, request that the device use this MAC address instead of its
941          * permanent MAC address.  This is known as MAC cloning or spoofing.
942          **/
943         g_object_class_install_property
944                 (object_class, PROP_CLONED_MAC_ADDRESS,
945                  _nm_param_spec_specialized (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "", "",
946                                              DBUS_TYPE_G_UCHAR_ARRAY,
947                                              G_PARAM_READWRITE |
948                                              NM_SETTING_PARAM_INFERRABLE |
949                                              G_PARAM_STATIC_STRINGS));
950     
951         /**
952          * NMSettingWired:mac-address-blacklist:
953          *
954          * If specified, this connection will never apply to the Ethernet device
955          * whose permanent MAC address matches an address in the list.  Each MAC
956          * address is in the standard hex-digits-and-colons notation
957          * (00:11:22:33:44:55).
958          **/
959         g_object_class_install_property
960                 (object_class, PROP_MAC_ADDRESS_BLACKLIST,
961                  _nm_param_spec_specialized (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, "", "",
962                                              DBUS_TYPE_G_LIST_OF_STRING,
963                                              G_PARAM_READWRITE |
964                                              NM_SETTING_PARAM_FUZZY_IGNORE |
965                                              G_PARAM_STATIC_STRINGS));
966
967         /**
968          * NMSettingWired:mtu:
969          *
970          * If non-zero, only transmit packets of the specified size or smaller,
971          * breaking larger packets up into multiple Ethernet frames.
972          **/
973         g_object_class_install_property
974                 (object_class, PROP_MTU,
975                  g_param_spec_uint (NM_SETTING_WIRED_MTU, "", "",
976                                     0, G_MAXUINT32, 0,
977                                     G_PARAM_READWRITE |
978                                     G_PARAM_CONSTRUCT |
979                                     NM_SETTING_PARAM_FUZZY_IGNORE |
980                                     G_PARAM_STATIC_STRINGS));
981
982         /**
983          * NMSettingWired:s390-subchannels:
984          *
985          * Identifies specific subchannels that this network device uses for
986          * communication with z/VM or s390 host.  Like the
987          * #NMSettingWired:mac-address property for non-z/VM devices, this property
988          * can be used to ensure this connection only applies to the network device
989          * that uses these subchannels.  The list should contain exactly 3 strings,
990          * and each string may only be composed of hexadecimal characters and the
991          * period (.) character.
992          **/
993         g_object_class_install_property
994                 (object_class, PROP_S390_SUBCHANNELS,
995                  _nm_param_spec_specialized (NM_SETTING_WIRED_S390_SUBCHANNELS, "", "",
996                                              DBUS_TYPE_G_ARRAY_OF_STRING,
997                                              G_PARAM_READWRITE |
998                                              NM_SETTING_PARAM_INFERRABLE |
999                                              G_PARAM_STATIC_STRINGS));
1000
1001         /**
1002          * NMSettingWired:s390-nettype:
1003          *
1004          * s390 network device type; one of "qeth", "lcs", or "ctc", representing
1005          * the different types of virtual network devices available on s390 systems.
1006          **/
1007         g_object_class_install_property
1008                 (object_class, PROP_S390_NETTYPE,
1009                  g_param_spec_string (NM_SETTING_WIRED_S390_NETTYPE, "", "",
1010                                       NULL,
1011                                       G_PARAM_READWRITE |
1012                                       NM_SETTING_PARAM_INFERRABLE |
1013                                       G_PARAM_STATIC_STRINGS));
1014
1015         /**
1016          * NMSettingWired:s390-options:
1017          *
1018          * Dictionary of key/value pairs of s390-specific device options.  Both keys
1019          * and values must be strings.  Allowed keys include "portno", "layer2",
1020          * "portname", "protocol", among others.  Key names must contain only
1021          * alphanumeric characters (ie, [a-zA-Z0-9]).
1022          **/
1023         g_object_class_install_property
1024                 (object_class, PROP_S390_OPTIONS,
1025                  _nm_param_spec_specialized (NM_SETTING_WIRED_S390_OPTIONS, "", "",
1026                                              DBUS_TYPE_G_MAP_OF_STRING,
1027                                              G_PARAM_READWRITE |
1028                                              NM_SETTING_PARAM_INFERRABLE |
1029                                              G_PARAM_STATIC_STRINGS));
1030 }