Send data to webserver from Arduino using Ethercad lib - php

i'm trying to send multiple data to a webserver using Ethercard library but for any reason is is only sending one data at a time.
Here is the the code I'm using:
#include <enc28j60.h>
#include <EtherCard.h>
#include <net.h>
#define HTTP_HEADER_OFFSET 163
#define MAX_STRINGS 100
#define MAX_STRING_LENGTH 8
/* Setup for Ethernet Library */
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
const char website[] PROGMEM = "www.arksecurity.net16.net";
const char device[] = "0004";
char test[MAX_STRINGS][MAX_STRING_LENGTH+1];
unsigned long timer;
unsigned long tempo = 5000;
String register[20];
unsigned int sentOK = 0;
char* localID[MAX_STRINGS];
int countRegister = 2;
//int countRegister = 1;
int countID;
byte Ethernet::buffer[700];
void setup()
{
Serial.begin(57600);
register[0] = "empty";
if (!ether.begin(sizeof Ethernet::buffer, mymac, 53))
{
Serial.println("Failed to access Ethernet controller");
while(1);
}
else
Serial.println("Ethernet controller initialized");
Serial.println();
if (!ether.dhcpSetup())
{
Serial.println("Failed to get configuration from DHCP");
while(1);
}
else
Serial.println("DHCP configuration done");
if (!ether.dnsLookup(website))
{
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
timer = millis() - tempo;
}
void loop()
{
char tempRegister[80];
ether.packetLoop(ether.packetReceive());
if (millis() - timer > tempo)
{
timer += tempo;
ether.browseUrl(PSTR("/DevicesQuery.php?device="), device , website, response_callback);
if(test[0][0] != 0)
{
int missing = 0;
Serial.println("Data Received");
for(int i = 0; i < countID ; i++)
{
for(int x = 0; x < 8 ; x++)
{
if (test[i][x] == '\0')
{
missing = 1;
}
}
}
if(missing)
{
Serial.println("Data Missing");
tempo = 5000;
}
else
{
for(int g; g < countID ; g++)
{
register[g] = String(test[g]);
}
tempo = 40000;
}
}
else{
Serial.println("Waiting for server response...");
tempo = 5000;
}
//register[0] = "?ID=1234";
//register[1] = "?ID=5678";
if(register[0] != "empty")
{
for(int i = 0; i < countRegister ; i++)
{
register[i].toCharArray(tempRegister, 80);
//delay(5000);
//Serial.println(tempRegister);
ether.browseUrl(PSTR("/log.php"), tempRegister , website, browser_callback);
//while(sentOK == 0);
//sentOK = 0;
}
countRegister = 0;
register[0] = "empty";
}
}
}
static void response_callback (byte status, word off, word len) {
for(int i=0;i<MAX_STRINGS;i++)
for(int j=0;j<=MAX_STRING_LENGTH;j++)
test[i][j] = 0;
int i_string = 0;
int i_char = 0;
int i_ethBuff = off + HTTP_HEADER_OFFSET;
char carat;
countID = 0;
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat = (char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
if (carat == '\n')
{ // New line char = new string
if (i_string < MAX_STRINGS - 1){
i_string++;
i_char = 0;
}
else
break; // Limite de memória do Arduino
}
else
{
if (i_char < MAX_STRING_LENGTH)
{
test[i_string][i_char] = carat;
i_char++;
} // otherwise discard the char (max length of string reached)
}
}
}
static void browser_callback (byte status, word off, word len)
{
Serial.println("Data sent");
//sentOK = 1;
}
countRegister is a variable and when it equals 1, it works great but, if he equals 2,for example, he only sends the second data to the server and ignore the first one. Anyone knows why is happening?
PS.:As for right now, I'm forcing register[0],register[1] values as you can see in the code above,but the idea is that later this values come from an outsource.

The short of it is that browseurl works asynchronously. Have a look at
http://forum.jeelabs.net/node/1477.html

Related

How to change arduino esp8266-01 it's wifi SSID and password through firebase and php?

I'm setting up The wifi SSID and Password of arduino specifically the esp-01 to be change by sending data (SSID & Password) to firebase then to PHP and to arduino
I tried many possible solutions and read articles that are related to what I wanted to be the result but none of it works
I am using an app to send data to firebase
Given the code for both Arduino and PHP (firebase)
Arduino code
#include <SoftwareSerial.h>
#include <DHT.h>;
SoftwareSerial Serial1(10, 11);
#define Trash "Trash3"
#define DHTTYPE DHT11
#define DHTPIN 2
#define TRIGGER_PIN 4
#define ECHO_PIN 3
DHT dht(DHTPIN, DHTTYPE, 11);
float humidity, temp_f;
int distance;
long duration;
String buff(64);
String getStr(128);
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
delay(2000);
Serial1.setTimeout(5000);
dht.begin();
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
if (!connectWiFi()) {
Serial.println("Can not connect to the WiFi.");
while (true);
}
Serial.println("OK, Connected to WiFi.");
sendCommand("AT+CIPSTA?");
sendCommand("AT+CIPSTAMAC?");}
void loop() {
temp_f = dht.readTemperature();
humidity = dht.readHumidity();
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH);
distance = duration * 0.034 / 2;
if (sendCommand("AT+CIPSTART=\"TCP\",\"gg.com\",80")) {
Serial.println("connected to Cloud");
getStr = "GET /upload.php?trash=";
getStr += Trash;
getStr += "&distance=";
getStr += distance;
getStr += "&temp_f=";
getStr += temp_f;
getStr += "&humidity=";
getStr += humidity;
getStr += " HTTP/1.1\r\n";
getStr += "Host: gg.com\r\n\r\n";
buff = "AT+CIPSEND=";
buff += getStr.length();
if (sendCommand(buff.c_str()) && Serial1.find(">")) {
Serial.println(getStr);
Serial1.print(getStr);
if (Serial1.find("+IPD,")) {
int l = Serial1.parseInt();
while (l > 0) {
if (Serial1.available()) {
Serial.write(Serial1.read());
l--;
}
}
Serial.println("--------------");
} else {
Serial.println("no response");
}
} else {
Serial.println("send error");
}
sendCommand("AT+CIPCLOSE");
} else {
Serial.println("Error connecting");
}
}
bool connectWiFi() {
if (!sendCommand("ATE0")) // echo off
return false;
if (!sendCommand("AT+CIPMUX=0")) // set single connection mode
return false;
if (!sendCommand("AT+CWMODE=1")) // set STA mode
return false;
return sendCommand("AT+CWJAP=\"CAPSTONE\",\"capstonemis\"");
}
bool sendCommand(const char* cmd) {
Serial.println(cmd);
Serial1.println(cmd);
while (true) {
buff = Serial1.readStringUntil('\n');
buff.trim();
if (buff.length() > 0) {
Serial.println(buff);
if (buff == "OK" || buff == "SEND OK" || buff == "ALREADY CONNECTED")
return true;
if (buff == "ERROR" || buff == "FAIL" || buff == "SEND FAIL")
return false;
}
}
}
PHP code
<?php
require 'firebaseLib.php';
$Trash = $_GET["trash"];
$Distance = $_GET["distance"];
$Temperature = $_GET["temp_f"];
$Humidity= $_GET["humidity"];
$baseURI = 'https://thesis1-69.firebaseio.com';
$token = 'gg';
$devicestatus= array('Distance' => $Distance,'Temperature' =>
$Temperature,'Humidity' => $Humidity);
$firebasePath = '/thesis1-69/';
$full= array($Trash => $devicestatus);
$fb = new Firebase($baseURI, $token);
$fb -> update($firebasePath, $full);
?>
I hope you can help me with the objective I wanted to finish
Thank you so much
more power!

Arduino ethernet shield php

I developed a code that counts the number of people passing in front of the infrared sensors.
But I wanted the arduino was a client and the FTP server consume these values. But I do not know php, but it would be something like this. The server is localhost.
file.ino:
#include <UIPEthernet.h>
EthernetServer server = EthernetServer(80);
int sensor1 = 8;
int sensor2 = 9;
unsigned long timeS1 = 0, timeS2 = 0;
unsigned long dif;
long int nPessoas = 0;
void setup()
{
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
Serial.begin(9600);
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
IPAddress myIP(192,168,0,25);
Ethernet.begin(mac,myIP);
server.begin();
}
void loop()
{
if (!digitalRead(sensor1))
{
timeS1 = millis();
}
if (!digitalRead(sensor2))
{
timeS2 = millis();
}
dif = timeS2 - timeS1;
dif = timeS2 - timeS1;
if(dif >= 500 && dif <= 1500)
{
timeS1 = timeS2 = 0;
nPessoas++;
}
size_t size;
if (EthernetClient client = server.available())
{
while((size = client.available()) > 0)
{
uint8_t* msg = (uint8_t*)malloc(size);
size = client.read(msg,size);
Serial.write(msg,size);
free(msg);
}
if (client.connect("http://192.168.0.7/",80)) {
client.println("POST /file.php HTTP/1.1");
client.println("Host: http://192.168.0.7/");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println();
client.print(nPessoas);
}
client.stop();
}
delay(10);
}
file.php:
<?Php
$value = $_GET {['nPessoas']};
echo $value;
?>
File.php:
<?php
$value = $_POST['nPessoas'];
echo $value;
?>
If it doesn't work by editing the php file, then try to add following before if (client.connect):
data = "nPessoas=" + nPessoas;
And then change client.print(nPessoas); to client.print(data);

auto-increment alphanumeric php , javascript

I want to make an auto-increment alphanumeric and this is just for output
if i press a button , there is an output AA001 and then i press a button again there is an output AA002
This doesn't use any 'clever' tricks but is shorter and easier to understand and tweak. It also uses numbers so it doesn't grow the length of the string as quickly. It increments from 0-9 then a-z, but it is intended that you should feed in 'a' to start with. Output always starts with an alphabet character, as long as your input also starts with an alphabet character, so it can be used as PHP variable names
var nextVarName = function(str) {
// Position of char to change.
var change = str.length - 1;
// The value of that char.
var change_char = str[change];
// Number of zeros to append when flipping.
var zeros = 0;
// Iterate backwards while there's a z (flipping).
while (change_char == 'z') {
// Increase the length of appended zeros
zeros++;
// Move the char to change back.
change_char = str[--change];
}
if (change_char == undefined) {
// Full flip - string increases in length.
str = 'a' + Array(str.length + 1).join("0");
} else {
// Normal increment with partial flip and 9->a handling.
str = str.substr(0, change)
+ (change_char == '9' ? 'a' : String.fromCharCode(str.charCodeAt(change) + 1))
+ Array(zeros + 1).join('0');
}
return str;
};
var vname = 'a';
for (var i = 0; i < 5; i++) {
vname = nextVarName(vname);
console.log(vname);
}
The results will be as follows:
z ---> a0
9z ---> a0 (unexpected input)
ab1zde ---> ab1zdf
abcdzz ---> abce00
zzzzz ---> a00000
abcyzz ---> abcz00
9000 ---> 9001 (unexpected input)
https://jsfiddle.net/e20kfvky/
The schedule of how many variables (that start with an alphabet char) are created of each length is as follows:
1: 26, 2: 936, 3: 33696, 4: 1213056 ... n: 36 ^ n - 10 * 36 ^ (n - 1)
The following code will generate a token that you can advance by one. It uses some small classes to make it modular. The function you attach to the button will call the function next on the token as shown in the very bottom.
//Element in a big token
function Increment(startval, endval) {
this.start = startval.charCodeAt(0);
this.cur = this.start;
this.end = endval.charCodeAt(0);
//Returns the current value
this.get = function() {
if (this.cur <= this.end) {
return String.fromCharCode(this.cur);
} else {
return null;
}
}
//Advances the value we will show
this.next = function() {
this.cur += 1;
return this.get();
}
//Reset it to the beginning
this.reset = function() {
this.cur = this.start;
}
}
function Token() {
this.token = [
new Increment("A", "Z"),
new Increment("A", "Z"),
new Increment("0", "9"),
new Increment("0", "9"),
new Increment("0", "9")
];
this.get = function() {
return this.token.map(function(cur) {
return cur.get();
}).join("");
}
this.next = function() {
//From the back to the front
for (var i = this.token.length - 1; i >= 0; i--) {
if (this.token[i].next() == null) {
//If we exhausted all possible values, continue
this.token[i].reset();
} else {
//Until we advance one that has still values left
break;
}
}
return this.get();
}
}
//Now we are just showing off...
var a = new Token();
for (var i = 0; i < 15; i++) {
console.log(a.next());
}
const getNextAlphaString = function (str) {
"use strict";
str=str.toUpperCase();
let chars;
chars = str.split("");
const strLen = str.length;
let continueIncermenting = true;
for (let i = strLen - 1; i >= 0; i = i - 1) {
let asciiVal;
asciiVal = chars[i].charCodeAt(0);
if (isNaN(asciiVal)) {
return str;
}
if (continueIncermenting === true) {
if (asciiVal >= 48 && asciiVal < 57) {
chars[i] = String.fromCharCode(asciiVal + 1);
continueIncermenting = false;
break;
} else if (asciiVal == 57) {
chars[i] = '0';
continueIncermenting = true;
}
if (asciiVal >= 65 && asciiVal < 90) {
chars[i] = String.fromCharCode(asciiVal + 1);
continueIncermenting = false;
break;
} else if (asciiVal == 90) {
chars[i] = String.fromCharCode(65);
continueIncermenting = true;
}
} else {
if (asciiVal == 90) {
continueIncermenting = true;
chars[i] = String.fromCharCode(65);
}
if (asciiVal == 57) {
continueIncermenting = true;
chars[i] = '0';
}
}
}
if (continueIncermenting === true) {
let firstAcii = chars[0].charCodeAt(0);
if (isNaN(firstAcii)) {
return str;
}
if ((firstAcii >= 65 && firstAcii <= 90) || (firstAcii >= 97 && firstAcii <= 122)) {
return 'A' + chars.join('').toUpperCase();
}
if (firstAcii >= 48 && firstAcii <= 57) {
return '0' + chars.join('').toUpperCase();
}
}
return chars.join('').toUpperCase();
};
The results will be as follows:
ab1zde ---> AB1ZDF
abcdzz ---> ABCEAA
zzzzz ---> AAAAAA
abcyzz ---> ABCZAA
9000 ---> 9001

Secure communication between arduino and PHP using RC4 and base64

I'm trying to make a mildly secure communication between Arduino and PHP. I can not use SSL for lack of power on the Arduino. So I wanted to use RC4 to encrypt data from PHP, and receive into the Arduino and decrypt. also encrypt from the Arduino and send to PHP.
The problem is that the encrypted data sent from PHP, do not coincide in the Arduino.
On PHP I get HesshwkfFk8Q in base64 and in the Arduino i get nZcwrlpZEr0V in base64.
different results when they should be equal.
I think I have a wrong Arduino RC4 implementation. I'm using this https://github.com/adamvr/arduino-base64
This is the code:
Arduino
#include <Base64.h>
unsigned char S[256];
char has[512];
#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
void rc4(char *key, char *data){
int i,j;
for (i=0;i<256;i++){
S[i] = i;
}
j = 0;
for (i=0;i<256;i++){
j = (j+S[i]+key[i%strlen(key)]) %256;
S_SWAP(S[i],S[j]);
}
i = j = 0;
for (int k=0;k<strlen(data);k++){
i = (i+1) %256;
j = (j+S[i]) %256;
S_SWAP(S[i],S[j]);
has[k] = data[k]^S[(S[i]+S[j]) %256];
}
has[strlen(data)+1] = '\0';
}
void setup() {
Serial.begin(9600);
char key[] = "Hello";
char sdata[] = "secretMsg";
rc4(key,sdata);
Serial.print("Encrypted : ");
char out[100];
base64_encode(out,has,strlen(has));
Serial.println(out);
char out2[100];
base64_decode(out2,out,strlen(out));
rc4(key,out2);
Serial.print("Decrypted : ");
Serial.println(has);
}
void loop(){
}
PHP
<?php
$key = 'Hello';
$msg = 'secretMsg';
$encrypted = rc4_crypt($key, $msg);
echo 'encrypted b64: ', base64_encode($encrypted) ,'<br>';
echo "decrip: " , rc4_decrypt($key,rc4_crypt($key, $msg));
exit;
function rc4_crypt($key,$msg) {
$td = mcrypt_module_open('arcfour', '' , 'stream', '');
mcrypt_generic_init($td, $key, null);
$encrypted = mcrypt_generic($td, $msg);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encrypted;
}
function rc4_decrypt($key,$msg) {
return rc4_crypt($key,$msg);
}
?>
I had the same problem and I can confirm you that your RC4 function in Arduino is wrong, you can use this instead:
unsigned char S[256];
unsigned int i, j;
void swap(unsigned char *s, unsigned int i, unsigned int j) {
unsigned char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
/* KSA */
void rc4_init(unsigned char *key, unsigned int key_length) {
for (i = 0; i < 256; i++)
S[i] = i;
for (i = j = 0; i < 256; i++) {
j = (j + key[i % key_length] + S[i]) & 255;
swap(S, i, j);
}
i = j = 0;
}
/* PRGA */
unsigned char rc4_output() {
i = (i + 1) & 255;
j = (j + S[i]) & 255;
swap(S, i, j);
return S[(S[i] + S[j]) & 255];
}
This is the current implementation that i'm using
#define SWAP(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
class RC4
{
public:
RC4 ()
{
memset(sbox,0,256);
memset(key,0,256);
}
virtual ~RC4 ()
{
memset(sbox,0,256);
memset(key,0,256);
}
char *Encrypt(char *pszText,const char *pszKey)
{
i=0, j=0,n = 0;
ilen = (int)strlen(pszKey);
for (m = 0; m < 256; m++)
{
*(key + m)= *(pszKey + (m % ilen));
*(sbox + m) = m;
}
for (m=0; m < 256; m++)
{
n = (n + *(sbox+m) + *(key + m)) &0xff;
SWAP(*(sbox + m),*(sbox + n));
}
ilen = (int)strlen(pszText);
for (m = 0; m < ilen; m++)
{
i = (i + 1) &0xff;
j = (j + *(sbox + i)) &0xff;
SWAP(*(sbox+i),*(sbox + j));
k = *(sbox + ((*(sbox + i) + *(sbox + j)) &0xff ));
if(k == *(pszText + m))
k = 0;
*(pszText + m) ^= k;
}
return pszText;
}
char *Decrypt(char *pszText,const char *pszKey)
{
return Encrypt(pszText,pszKey) ;
}
private:
unsigned char sbox[256];
unsigned char key[256],k;
int m, n, i, j, ilen;
};
;
After a lot of trials without success I ended up with the following three codes:
Arduino code implemented RC4 (adapted from this C code) and encoding the encrypted result in Base64
PHP code that decodes base64 and decrypts RC4
HTML to test the PHP (and eventually it will be the index of ESP32 Webserver). ATTENTION! sending Base64 in the Url can be dangerous becasue the characters '+' '/' '=' can create problems, so make sure you read this post Base64 in url and the charachters that can be problematic are replaced by '.' '_' '-'
At time of writing I am using Arduino core for ESP32 version 2.0.0 consider that if you are not using this version of Base64.h there could be incompatibility (more details here)
Arduino Code
#include <stdio.h>
#include <string.h>
#include "base64.h"
typedef unsigned long ULONG;
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len)
{
int i =0, j = 0;
char k[256] = {0};
unsigned char tmp = 0;
for (i=0;i<256;i++) {
s[i] = i;
k[i] = key[i%Len];
}
for (i=0; i<256; i++) {
j=(j+s[i]+k[i])%256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for(k=0;k<Len;k++) {
i=(i+1)%256;
j=(j+s[i])%256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t=(s[i]+s[j])%256;
Data[k] ^= s[t];
}
}
int main()
{
unsigned char s[256] = {0}; //S-box
char key[256] = "Hello";
char pData[512] = "secretMsg";
ULONG len = strlen(pData);
printf("key : %s\n", key);
printf("raw : %s\n", pData);
rc4_init(s,(unsigned char *)key,strlen(key));
rc4_crypt(s,(unsigned char *)pData,len);
printf("encrypt : %s\n", pData);
base64 b;
String encoded = b.encode((unsigned char *)pData, strlen(pData));
Serial.println(encoded);
rc4_init(s,(unsigned char *)key, strlen(key));
rc4_crypt(s,(unsigned char *)pData,len);
printf("decrypt : %s\n",pData);
return 0;
}
void setup(){
Serial.begin(115200);
main();
}
void loop(){
}
PHP CODE
<?php
function rc4_crypt($key,$msg) {
$td = mcrypt_module_open('arcfour', '' , 'stream', '');
mcrypt_generic_init($td, $key, null);
$encrypted = mcrypt_generic($td, $msg);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encrypted;
}
function rc4_decrypt($key,$msg) {
return rc4_crypt($key,$msg);
}
if(isset($_POST['base'])) {
$key = 'Hello';
$msg_revealed = $_POST['base'];
rc4_decrypt($key, base64_decode($msg_revealed)) //decode form base64 and decrypt
$msg = 'secretMsg'; //for testing
$encrypted = rc4_crypt($key, $msg);
echo 'encrypted b64: ', base64_encode($encrypted) ,'<br>';
echo "decrip: " , rc4_decrypt($key,rc4_crypt($key, $msg));
exit;
}
?>
HTML CODE FOR TESTING and eventually the code that will be hosted on ESP32 webserver (more info here)
<html >
<head>
<title>test Base64</title>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='generator' content='Geany 1.36' />
</head>
<body>
<form action='https://www.yourwebsite.com/base64.php' method='post' id='downloadForm'>
<input hidden name='base' value='PASS_THE_URL_BASE64_ENCRYPTED_STRING_HERE'>
</form>
<div style='text-align: center;'><button type='button' class='btn btn-danger' onclick='sendBaseForm()'>TEST</button></div>
</body>
<script>
function sendBaseForm(){
document.getElementById('downloadForm').submit();
}
</script>
</html>

Increment individual IPs from IPv6 string (php)

What is a simple, elegant way to list the first x number of IPv6 IPs from a IPv6 string.
For example,
listIPs("2600:f333:10:c000::0", 4)
echos
2600:f333:10:c000::1
2600:f333:10:c000::2
2600:f333:10:c000::3
2600:f333:10:c000::4
Here's a sample of code that may have worked for IPv4, as it converted to int:
$input = "2600:f333:10:c000::/51";
$max = 4;
list($block, $cidr) = explode("/", $input);
$first = inet_pton( $block );
echo inet_ntop($first) . "\n";
for ($i = 1; $i < $max; $i++) {
//todo: die if it has exceeded block size based on $cidr
echo inet_ntop($first + $i) . "\n"; //doesn't work, packed binary?
}
Here's an example program written in C (since I don't know C++). It's fairly fast, but I'm not really happy with it. Maybe someone can help me improve it.
Edit: Obviously, I wrote this before it was turned into a PHP-only question. Turning this into PHP is left as an exercise to the reader (ew).
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
/*
* Syntax: ./ipv6_list <ip>/<cidr-prefix>
*/
int main(int argc, char **argv) {
uint8_t start[16];
uint8_t address[16];
uint8_t mask[16] = { 0 };
uint8_t prefix = 128;
char *prefix_location;
int i;
/* This is the octet that, when changed, will result in <IP> & <mask> != <start IP> */
int mask_check_octet = 0;
if(argc != 2)
return 1;
/* Find prefix */
if((prefix_location = strstr(argv[1], "/")) != NULL) {
char *prefix_search = prefix_location + 1;
char *prefix_remaining;
long prefix_test;
if(!isdigit(*prefix_search))
return 2;
errno = 0;
prefix_test = strtol(prefix_search, &prefix_remaining, 10);
if(errno == ERANGE || prefix_test < 0 || prefix_test > 128 || strcmp(prefix_remaining, "") != 0)
return 2;
prefix = (uint8_t)prefix_test;
*prefix_location = '\0'; /* So we can just pass argv[1] into inet_pton(3) */
}
/* Convert prefix into mask */
for(i = 0; i < 16; i++) {
if(prefix == 0)
break;
mask_check_octet = i;
if(prefix < 8) {
mask[i] = ~((1 << (8 - prefix)) - 1);
break;
}
else
mask[i] = UINT8_MAX;
prefix -= 8;
}
/* Find address */
if(inet_pton(AF_INET6, argv[1], start) != 1)
return 3;
/* Start at the beginning of the network */
for(i = 0; i < 16; i++) {
start[i] &= mask[i];
address[i] = start[i];
}
/* Iterate */
while((address[mask_check_octet] & mask[mask_check_octet]) == start[mask_check_octet]) {
char address_str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, address, address_str, sizeof(address_str));
printf("%s\n", address_str);
/* Add one to the address */
for(i = 15; i >= 0; i--) {
if(address[i] != UINT8_MAX)
break;
}
address[i]++;
for(i++; i < 16; i++)
address[i] = 0;
};
return 0;
}
You can use standard shell commands to limit its output (or just modify the while loop):
nfontes#brioche:~$ ./ipv6_list '2607:fc50:0:d00::0/106' | head -n 200
2607:fc50:0:d00::
2607:fc50:0:d00::1
2607:fc50:0:d00::2
2607:fc50:0:d00::3
2607:fc50:0:d00::4
2607:fc50:0:d00::5
2607:fc50:0:d00::6
2607:fc50:0:d00::7
2607:fc50:0:d00::8
2607:fc50:0:d00::9
2607:fc50:0:d00::a
2607:fc50:0:d00::b
2607:fc50:0:d00::c
2607:fc50:0:d00::d
2607:fc50:0:d00::e
[...]
2607:fc50:0:d00::c0
2607:fc50:0:d00::c1
2607:fc50:0:d00::c2
2607:fc50:0:d00::c3
2607:fc50:0:d00::c4
2607:fc50:0:d00::c5
2607:fc50:0:d00::c6
2607:fc50:0:d00::c7
Something similar (in PHP). It takes an IPv4/IPv6 address and increments it by given value:
// Takes an IPv4/IPv6 address in string format, and increments it by given value
function incrementIp($ip, $increment)
{
$addr = inet_pton ( $ip );
for ( $i = strlen ( $addr ) - 1; $increment > 0 && $i >= 0; --$i )
{
$val = ord($addr[$i]) + $increment;
$increment = $val / 256;
$addr[$i] = chr($val % 256);
}
return inet_ntop ( $addr );
}

Categories