return err;
        }
        if (data[IFLA_BOND_ARP_IP_TARGET]) {
-               __be32 targets[BOND_MAX_ARP_TARGETS] = { 0, };
                struct nlattr *attr;
                int i = 0, rem;
 
+               bond_option_arp_ip_targets_clear(bond);
                nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
                        __be32 target = nla_get_be32(attr);
-                       targets[i++] = target;
-               }
 
-               err = bond_option_arp_ip_targets_set(bond, targets, i);
+                       bond_opt_initval(&newval, target);
+                       err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
+                                            &newval);
+                       if (err)
+                               break;
+                       i++;
+               }
+               if (i == 0 && bond->params.arp_interval)
+                       pr_warn("%s: removing last arp target with arp_interval on\n",
+                               bond->dev->name);
                if (err)
                        return err;
        }
 
 #include <linux/rwlock.h>
 #include <linux/rcupdate.h>
 #include <linux/ctype.h>
+#include <linux/inet.h>
 #include "bonding.h"
 
 static struct bond_opt_value bond_mode_tbl[] = {
                .values = bond_intmax_tbl,
                .set = bond_option_arp_interval_set
        },
+       [BOND_OPT_ARP_TARGETS] = {
+               .id = BOND_OPT_ARP_TARGETS,
+               .name = "arp_ip_target",
+               .desc = "arp targets in n.n.n.n form",
+               .flags = BOND_OPTFLAG_RAWVAL,
+               .set = bond_option_arp_ip_targets_set
+       },
        { }
 };
 
        return 0;
 }
 
-int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
-                                  int count)
+void bond_option_arp_ip_targets_clear(struct bonding *bond)
 {
-       int i, ret = 0;
+       int i;
 
        /* not to race with bond_arp_rcv */
        write_lock_bh(&bond->lock);
-
-       /* clear table */
        for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
                _bond_options_arp_ip_target_set(bond, i, 0, 0);
+       write_unlock_bh(&bond->lock);
+}
 
-       if (count == 0 && bond->params.arp_interval)
-               pr_warn("%s: removing last arp target with arp_interval on\n",
-                       bond->dev->name);
-
-       for (i = 0; i < count; i++) {
-               ret = _bond_option_arp_ip_target_add(bond, targets[i]);
-               if (ret)
-                       break;
+int bond_option_arp_ip_targets_set(struct bonding *bond,
+                                  struct bond_opt_value *newval)
+{
+       int ret = -EPERM;
+       __be32 target;
+
+       if (newval->string) {
+               if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) {
+                       pr_err("%s: invalid ARP target %pI4 specified\n",
+                              bond->dev->name, &target);
+                       return ret;
+               }
+               if (newval->string[0] == '+')
+                       ret = bond_option_arp_ip_target_add(bond, target);
+               else if (newval->string[0] == '-')
+                       ret = bond_option_arp_ip_target_rem(bond, target);
+               else
+                       pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
+                              bond->dev->name);
+       } else {
+               target = newval->value;
+               ret = bond_option_arp_ip_target_add(bond, target);
        }
 
-       write_unlock_bh(&bond->lock);
        return ret;
 }
 
 
        BOND_OPT_ARP_ALL_TARGETS,
        BOND_OPT_FAIL_OVER_MAC,
        BOND_OPT_ARP_INTERVAL,
+       BOND_OPT_ARP_TARGETS,
        BOND_OPT_LAST
 };
 
                                  struct bond_opt_value *newval);
 int bond_option_arp_interval_set(struct bonding *bond,
                                 struct bond_opt_value *newval);
+int bond_option_arp_ip_targets_set(struct bonding *bond,
+                                  struct bond_opt_value *newval);
+void bond_option_arp_ip_targets_clear(struct bonding *bond);
 #endif /* _BOND_OPTIONS_H */
 
                                        struct device_attribute *attr,
                                        char *buf)
 {
-       int i, res = 0;
        struct bonding *bond = to_bond(d);
+       int i, res = 0;
 
        for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
                if (bond->params.arp_targets[i])
        }
        if (res)
                buf[res-1] = '\n'; /* eat the leftover space */
+
        return res;
 }
 
                                         const char *buf, size_t count)
 {
        struct bonding *bond = to_bond(d);
-       __be32 target;
-       int ret = -EPERM;
-
-       if (!in4_pton(buf + 1, -1, (u8 *)&target, -1, NULL)) {
-               pr_err("%s: invalid ARP target %pI4 specified\n",
-                      bond->dev->name, &target);
-               return -EPERM;
-       }
-
-       if (!rtnl_trylock())
-               return restart_syscall();
-
-       if (buf[0] == '+')
-               ret = bond_option_arp_ip_target_add(bond, target);
-       else if (buf[0] == '-')
-               ret = bond_option_arp_ip_target_rem(bond, target);
-       else
-               pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
-                      bond->dev->name);
+       int ret;
 
+       ret = bond_opt_tryset_rtnl(bond, BOND_OPT_ARP_TARGETS, (char *)buf);
        if (!ret)
                ret = count;
 
-       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
 
 int bond_option_updelay_set(struct bonding *bond, int updelay);
 int bond_option_downdelay_set(struct bonding *bond, int downdelay);
 int bond_option_use_carrier_set(struct bonding *bond, int use_carrier);
-int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
-                                  int count);
 int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target);
 int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target);
 int bond_option_primary_set(struct bonding *bond, const char *primary);