/* * Tmpfile.upload(path, offset, data) */ static dbus_bool_t __ni_Testbus_Agent_Filesystem_upload(ni_dbus_object_t *object, const ni_dbus_method_t *method, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { ni_buffer_t wbuf; const char *path; uint64_t offset; unsigned int written = 0; int fd; if (argc != 3 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/' || !ni_dbus_variant_get_uint64(&argv[1], &offset) || !ni_dbus_variant_is_byte_array(&argv[2])) return ni_dbus_error_invalid_args(error, object->path, method->name); if (offset == 0) fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644); else fd = open(path, O_WRONLY); if (fd < 0) { ni_dbus_set_error_from_errno(error, errno, "unable to open file \"%s\"", path); return FALSE; } if (lseek(fd, offset, SEEK_SET) < 0) { ni_dbus_set_error_from_errno(error, errno, "seek faile"); goto out_fail; } ni_buffer_init_reader(&wbuf, argv[2].byte_array_value, argv[2].array.len); while (ni_buffer_count(&wbuf)) { int n; n = write(fd, ni_buffer_head(&wbuf), ni_buffer_count(&wbuf)); if (n < 0) { ni_dbus_set_error_from_errno(error, errno, "error writing to \"%s\" at offset %Lu", path, (unsigned long long) offset + written); goto out_fail; } ni_buffer_pull_head(&wbuf, n); written += n; } close(fd); ni_debug_testbus("%s: wrote %u bytes at offset %Lu", path, written, (unsigned long long) offset); return TRUE; out_fail: if (fd >= 0) close(fd); return FALSE; }
int ni_arp_parse(ni_arp_socket_t *arph, ni_buffer_t *bp, ni_arp_packet_t *p) { struct arphdr *arp; if (!(arp = ni_buffer_pull_head(bp, sizeof(*arp)))) return -1; if (arp->ar_pro != htons(ETHERTYPE_IP) || arp->ar_pln != 4) return -1; p->op = ntohs(arp->ar_op); p->sha.type = arph->dev_info.hwaddr.type; p->sha.len = ni_link_address_length(arph->dev_info.hwaddr.type); p->tha = p->sha; if (ni_buffer_get(bp, p->sha.data, p->sha.len) < 0 || ni_buffer_get(bp, &p->sip, 4) < 0 || ni_buffer_get(bp, p->tha.data, p->tha.len) < 0 || ni_buffer_get(bp, &p->tip, 4) < 0) return -1; return 0; }
int ni_dhcp4_fsm_process_dhcp4_packet(ni_dhcp4_device_t *dev, ni_buffer_t *msgbuf) { ni_dhcp4_message_t *message; ni_addrconf_lease_t *lease = NULL; int msg_code; if (dev->fsm.state == NI_DHCP4_STATE_VALIDATING) { /* We arrive here, when some dhcp4 packet arrives after * we've got and processed an ACK already. Just ignore. */ ni_debug_dhcp("%s: ignoring dhcp4 packet arrived in state VALIDATING", dev->ifname); return -1; } if (!(message = ni_buffer_pull_head(msgbuf, sizeof(*message)))) { ni_debug_dhcp("short DHCP4 packet (%u bytes)", ni_buffer_count(msgbuf)); return -1; } if (dev->dhcp4.xid == 0) { ni_debug_dhcp("unexpected packet on %s", dev->ifname); return -1; } if (dev->dhcp4.xid != message->xid) { ni_debug_dhcp("ignoring packet with wrong xid 0x%x (expected 0x%x)", message->xid, dev->dhcp4.xid); return -1; } msg_code = ni_dhcp4_parse_response(message, msgbuf, &lease); if (msg_code < 0) { /* Ignore this message, time out later */ ni_error("unable to parse DHCP4 response"); return -1; } /* set reqest client-id in the response early to have it in test mode */ ni_opaque_set(&lease->dhcp4.client_id, dev->config->client_id.data, dev->config->client_id.len); ni_debug_dhcp("%s: received %s message in state %s", dev->ifname, ni_dhcp4_message_name(msg_code), ni_dhcp4_fsm_state_name(dev->fsm.state)); /* When receiving a DHCP4 OFFER, verify sender address against list of * servers to ignore, and preferred servers. */ if (msg_code == DHCP4_OFFER && dev->fsm.state == NI_DHCP4_STATE_SELECTING) { struct in_addr srv_addr = lease->dhcp4.server_id; int weight = 0; if (ni_dhcp4_config_ignore_server(srv_addr)) { ni_debug_dhcp("%s: ignoring DHCP4 offer from %s", dev->ifname, inet_ntoa(srv_addr)); goto out; } /* If we're scanning all offers, we need to decide whether * this offer is accepted, or whether we want to wait for * more. */ if (!dev->dhcp4.accept_any_offer) { /* Check if we have any preferred servers. */ weight = ni_dhcp4_config_server_preference(srv_addr); /* If we're refreshing an existing lease (eg after link disconnect * and reconnect), we accept the offer if it comes from the same * server as the original one. */ if (dev->lease && dev->lease->dhcp4.server_id.s_addr == srv_addr.s_addr) weight = 100; ni_debug_dhcp("received lease offer from %s; server weight=%d (best offer=%d)", inet_ntoa(lease->dhcp4.server_id), weight, dev->best_offer.weight); /* negative weight means never. */ if (weight < 0) goto out; /* weight between 0 and 100 means maybe. */ if (weight < 100) { if (dev->best_offer.weight < weight) { ni_dhcp4_device_set_best_offer(dev, lease, weight); return 0; } goto out; } /* If the weight has maximum value, just accept this offer. */ } ni_dhcp4_device_set_best_offer(dev, lease, weight); lease = NULL; } /* We've received a valid response; if something goes wrong now * it's nothing that could be fixed by retransmitting the message. * * The only exception would be if we ever do some filtering or * matching of OFFERs - then we would certainly want to keep * waiting for additional packets. */ ni_dhcp4_device_disarm_retransmit(dev); dev->dhcp4.xid = 0; /* move to next stage of protocol */ switch (msg_code) { case DHCP4_OFFER: if (dev->fsm.state != NI_DHCP4_STATE_SELECTING) goto ignore; /* process best offer set above */ ni_dhcp4_process_offer(dev, dev->best_offer.lease); break; case DHCP4_ACK: if (dev->fsm.state == NI_DHCP4_STATE_INIT) { /* * Received a decline ACK -- wait until * timeout before we restart from begin */ ni_dhcp4_device_drop_lease(dev); break; } if (dev->fsm.state != NI_DHCP4_STATE_REQUESTING && dev->fsm.state != NI_DHCP4_STATE_RENEWING && dev->fsm.state != NI_DHCP4_STATE_REBOOT && dev->fsm.state != NI_DHCP4_STATE_REBINDING) goto ignore; ni_dhcp4_process_ack(dev, lease); lease = NULL; break; case DHCP4_NAK: /* The RFC 2131 state diagram says, ignore NAKs in state BOUND. * I guess we also have no use for NAK replies to a DHCP4_DISCOVER */ if (dev->fsm.state == NI_DHCP4_STATE_SELECTING || dev->fsm.state == NI_DHCP4_STATE_BOUND) goto ignore; ni_dhcp4_process_nak(dev); break; default: ignore: ni_debug_dhcp("ignoring %s in state %s", ni_dhcp4_message_name(msg_code), ni_dhcp4_fsm_state_name(dev->fsm.state)); break; } out: if (lease && dev->lease != lease) ni_addrconf_lease_free(lease); /* If we received a message other than NAK, reset the NAK * backoff timer. */ if (msg_code != DHCP4_NAK) dev->dhcp4.nak_backoff = 1; return 0; }