mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-06-19 12:37:20 +08:00
Remove lwIP 1.3.2 and yaffs2 from RT-Thread Platform.
This commit is contained in:
@@ -1,398 +0,0 @@
|
||||
diff --git a/dfs_yaffs2.c b/dfs_yaffs2.c
|
||||
index 4b056ae..e63d5d4 100644
|
||||
--- a/dfs_yaffs2.c
|
||||
+++ b/dfs_yaffs2.c
|
||||
@@ -39,7 +39,6 @@ static int dfs_yaffs_mount(struct dfs_filesystem* fs,
|
||||
const void* data)
|
||||
{
|
||||
unsigned index;
|
||||
- ynandif_Geometry *g;
|
||||
|
||||
/*1. find a empty entry in partition table */
|
||||
for (index = 0; index < NAND_DEVICE_PART_MAX ; index ++)
|
||||
diff --git a/yaffs/direct/yaffsfs.c b/yaffs/direct/yaffsfs.c
|
||||
index 17fc502..1f47ea7 100644
|
||||
--- a/yaffs/direct/yaffsfs.c
|
||||
+++ b/yaffs/direct/yaffsfs.c
|
||||
@@ -1367,7 +1367,7 @@ off_t yaffs_lseek(int handle, off_t offset, int whence)
|
||||
if(offset >= 0)
|
||||
pos = offset;
|
||||
} else if(whence == SEEK_CUR) {
|
||||
- if( (fd->position + offset) >= 0)
|
||||
+ if( ((int)fd->position + offset) >= 0)
|
||||
pos = (fd->position + offset);
|
||||
} else if(whence == SEEK_END) {
|
||||
fSize = yaffs_get_obj_length(obj);
|
||||
diff --git a/yaffs/direct/yportenv.h b/yaffs/direct/yportenv.h
|
||||
index f693c16..ac0a737 100644
|
||||
--- a/yaffs/direct/yportenv.h
|
||||
+++ b/yaffs/direct/yportenv.h
|
||||
@@ -45,7 +45,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef loff_t
|
||||
- typedef unsigned long loff_t;
|
||||
+ typedef long loff_t;
|
||||
#endif
|
||||
|
||||
#ifndef dev_t
|
||||
@@ -66,7 +66,7 @@
|
||||
#elif defined (__GNUC__) && !defined(__CC_ARM)
|
||||
|
||||
#ifndef loff_t
|
||||
- typedef unsigned long loff_t;
|
||||
+ typedef long loff_t;
|
||||
#endif
|
||||
|
||||
#ifndef dev_t
|
||||
diff --git a/yaffs/yaffs_guts.c b/yaffs/yaffs_guts.c
|
||||
index d72aa5b..08db8c8 100644
|
||||
--- a/yaffs/yaffs_guts.c
|
||||
+++ b/yaffs/yaffs_guts.c
|
||||
@@ -280,7 +280,7 @@ static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk,
|
||||
|
||||
static inline int yaffs_hash_fn(int n)
|
||||
{
|
||||
- n = abs(n);
|
||||
+ n = n > 0 ? n : -n;
|
||||
return n % YAFFS_NOBJECT_BUCKETS;
|
||||
}
|
||||
|
||||
@@ -319,9 +319,9 @@ static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk)
|
||||
int retval = YAFFS_OK;
|
||||
u8 *data = yaffs_get_temp_buffer(dev);
|
||||
struct yaffs_ext_tags tags;
|
||||
- int result;
|
||||
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
|
||||
+
|
||||
+ yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
|
||||
|
||||
if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
|
||||
retval = YAFFS_FAIL;
|
||||
@@ -347,9 +347,9 @@ static int yaffs_verify_chunk_written(struct yaffs_dev *dev,
|
||||
int retval = YAFFS_OK;
|
||||
struct yaffs_ext_tags temp_tags;
|
||||
u8 *buffer = yaffs_get_temp_buffer(dev);
|
||||
- int result;
|
||||
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
|
||||
+
|
||||
+ yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
|
||||
if (memcmp(buffer, data, dev->data_bytes_per_chunk) ||
|
||||
temp_tags.obj_id != tags->obj_id ||
|
||||
temp_tags.chunk_id != tags->chunk_id ||
|
||||
@@ -1478,7 +1478,7 @@ static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
|
||||
struct yaffs_obj *the_obj;
|
||||
int usage;
|
||||
int i;
|
||||
- int pushout;
|
||||
+ /* int pushout; */
|
||||
|
||||
if (dev->param.n_caches < 1)
|
||||
return NULL;
|
||||
@@ -1499,7 +1499,7 @@ static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
|
||||
the_obj = dev->cache[0].object;
|
||||
usage = -1;
|
||||
cache = NULL;
|
||||
- pushout = -1;
|
||||
+ /* pushout = -1; */
|
||||
|
||||
for (i = 0; i < dev->param.n_caches; i++) {
|
||||
if (dev->cache[i].object &&
|
||||
@@ -1509,7 +1509,7 @@ static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
|
||||
usage = dev->cache[i].last_use;
|
||||
the_obj = dev->cache[i].object;
|
||||
cache = &dev->cache[i];
|
||||
- pushout = i;
|
||||
+ /* pushout = i; */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3167,7 +3167,7 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
|
||||
struct yaffs_obj_hdr *oh;
|
||||
struct yaffs_dev *dev;
|
||||
struct yaffs_ext_tags tags;
|
||||
- int result;
|
||||
+
|
||||
int alloc_failed = 0;
|
||||
|
||||
if (!in || !in->lazy_loaded || in->hdr_chunk < 1)
|
||||
@@ -3177,7 +3177,7 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
|
||||
in->lazy_loaded = 0;
|
||||
buf = yaffs_get_temp_buffer(dev);
|
||||
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
|
||||
+ yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
|
||||
oh = (struct yaffs_obj_hdr *)buf;
|
||||
|
||||
in->yst_mode = oh->yst_mode;
|
||||
@@ -3189,6 +3189,7 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
|
||||
yaffs_clone_str(oh->alias);
|
||||
if (!in->variant.symlink_variant.alias)
|
||||
alloc_failed = 1; /* Not returned */
|
||||
+ alloc_failed = alloc_failed;
|
||||
}
|
||||
yaffs_release_temp_buffer(dev, buf);
|
||||
}
|
||||
@@ -3274,7 +3275,7 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
|
||||
struct yaffs_dev *dev = in->my_dev;
|
||||
int prev_chunk_id;
|
||||
int ret_val = 0;
|
||||
- int result = 0;
|
||||
+
|
||||
int new_chunk_id;
|
||||
struct yaffs_ext_tags new_tags;
|
||||
struct yaffs_ext_tags old_tags;
|
||||
@@ -3297,7 +3298,7 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
|
||||
prev_chunk_id = in->hdr_chunk;
|
||||
|
||||
if (prev_chunk_id > 0) {
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
|
||||
+ yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
|
||||
buffer, &old_tags);
|
||||
|
||||
yaffs_verify_oh(in, oh, &old_tags, 0);
|
||||
@@ -3921,7 +3922,7 @@ int yaffs_del_obj(struct yaffs_obj *obj)
|
||||
list_del_init(&obj->variant.dir_variant.dirty);
|
||||
}
|
||||
return yaffs_del_dir(obj);
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_SYMLINK:
|
||||
ret_val = yaffs_del_symlink(obj);
|
||||
break;
|
||||
@@ -3993,17 +3994,17 @@ static int yaffs_unlink_worker(struct yaffs_obj *obj)
|
||||
switch (obj->variant_type) {
|
||||
case YAFFS_OBJECT_TYPE_FILE:
|
||||
return yaffs_del_file(obj);
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_DIRECTORY:
|
||||
list_del_init(&obj->variant.dir_variant.dirty);
|
||||
return yaffs_del_dir(obj);
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_SYMLINK:
|
||||
return yaffs_del_symlink(obj);
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_SPECIAL:
|
||||
return yaffs_generic_obj_del(obj);
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_HARDLINK:
|
||||
case YAFFS_OBJECT_TYPE_UNKNOWN:
|
||||
default:
|
||||
@@ -4421,7 +4422,7 @@ int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size)
|
||||
} else if (obj->short_name[0]) {
|
||||
strcpy(name, obj->short_name);
|
||||
} else if (obj->hdr_chunk > 0) {
|
||||
- int result;
|
||||
+
|
||||
u8 *buffer = yaffs_get_temp_buffer(obj->my_dev);
|
||||
|
||||
struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)buffer;
|
||||
@@ -4429,7 +4430,7 @@ int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size)
|
||||
memset(buffer, 0, obj->my_dev->data_bytes_per_chunk);
|
||||
|
||||
if (obj->hdr_chunk > 0) {
|
||||
- result = yaffs_rd_chunk_tags_nand(obj->my_dev,
|
||||
+ yaffs_rd_chunk_tags_nand(obj->my_dev,
|
||||
obj->hdr_chunk,
|
||||
buffer, NULL);
|
||||
}
|
||||
@@ -4490,16 +4491,16 @@ unsigned yaffs_get_obj_type(struct yaffs_obj *obj)
|
||||
switch (obj->variant_type) {
|
||||
case YAFFS_OBJECT_TYPE_FILE:
|
||||
return DT_REG;
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_DIRECTORY:
|
||||
return DT_DIR;
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_SYMLINK:
|
||||
return DT_LNK;
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_HARDLINK:
|
||||
return DT_REG;
|
||||
- break;
|
||||
+ //break;
|
||||
case YAFFS_OBJECT_TYPE_SPECIAL:
|
||||
if (S_ISFIFO(obj->yst_mode))
|
||||
return DT_FIFO;
|
||||
@@ -4510,10 +4511,10 @@ unsigned yaffs_get_obj_type(struct yaffs_obj *obj)
|
||||
if (S_ISSOCK(obj->yst_mode))
|
||||
return DT_SOCK;
|
||||
return DT_REG;
|
||||
- break;
|
||||
+ //break;
|
||||
default:
|
||||
return DT_REG;
|
||||
- break;
|
||||
+ //break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4837,7 +4838,7 @@ int yaffs_guts_initialise(struct yaffs_dev *dev)
|
||||
dev->n_erased_blocks = 0;
|
||||
dev->n_free_chunks = 0;
|
||||
dev->alloc_block = -1;
|
||||
- dev->alloc_page = -1;
|
||||
+ dev->alloc_page = (u32)(-1);
|
||||
dev->n_deleted_files = 0;
|
||||
dev->n_unlinked_files = 0;
|
||||
dev->n_bg_deletions = 0;
|
||||
diff --git a/yaffs/yaffs_packedtags2.c b/yaffs/yaffs_packedtags2.c
|
||||
index 820bc41..9306623 100644
|
||||
--- a/yaffs/yaffs_packedtags2.c
|
||||
+++ b/yaffs/yaffs_packedtags2.c
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
/* Also, the top 4 bits of the object Id are set to the object type. */
|
||||
#define EXTRA_OBJECT_TYPE_SHIFT (28)
|
||||
-#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT)
|
||||
+#define EXTRA_OBJECT_TYPE_MASK ((0x0fUL) << EXTRA_OBJECT_TYPE_SHIFT)
|
||||
|
||||
static void yaffs_dump_packed_tags2_tags_only(
|
||||
const struct yaffs_packed_tags2_tags_only *ptt)
|
||||
@@ -129,7 +129,7 @@ void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
|
||||
t->extra_parent_id = ptt->chunk_id & (~(ALL_EXTRA_FLAGS));
|
||||
t->extra_is_shrink = ptt->chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0;
|
||||
t->extra_shadows = ptt->chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0;
|
||||
- t->extra_obj_type = ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT;
|
||||
+ t->extra_obj_type = (enum yaffs_obj_type)(ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT);
|
||||
t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
|
||||
|
||||
if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
|
||||
diff --git a/yaffs/yaffs_verify.c b/yaffs/yaffs_verify.c
|
||||
index b3e540d..1758125 100644
|
||||
--- a/yaffs/yaffs_verify.c
|
||||
+++ b/yaffs/yaffs_verify.c
|
||||
@@ -223,7 +223,7 @@ void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
|
||||
void yaffs_verify_file(struct yaffs_obj *obj)
|
||||
{
|
||||
int required_depth;
|
||||
- int actual_depth;
|
||||
+ //int actual_depth;
|
||||
u32 last_chunk;
|
||||
u32 the_chunk;
|
||||
u32 x;
|
||||
@@ -252,7 +252,7 @@ void yaffs_verify_file(struct yaffs_obj *obj)
|
||||
required_depth++;
|
||||
}
|
||||
|
||||
- actual_depth = obj->variant.file_variant.top_level;
|
||||
+ //actual_depth = obj->variant.file_variant.top_level;
|
||||
|
||||
/* Check that the chunks in the tnode tree are all correct.
|
||||
* We do this by scanning through the tnode tree and
|
||||
diff --git a/yaffs/yaffs_yaffs1.c b/yaffs/yaffs_yaffs1.c
|
||||
index da6a40f..8e7f4b2 100644
|
||||
--- a/yaffs/yaffs_yaffs1.c
|
||||
+++ b/yaffs/yaffs_yaffs1.c
|
||||
@@ -23,7 +23,7 @@ int yaffs1_scan(struct yaffs_dev *dev)
|
||||
{
|
||||
struct yaffs_ext_tags tags;
|
||||
int blk;
|
||||
- int result;
|
||||
+ //int result;
|
||||
int chunk;
|
||||
int c;
|
||||
int deleted;
|
||||
@@ -84,7 +84,7 @@ int yaffs1_scan(struct yaffs_dev *dev)
|
||||
cond_resched();
|
||||
|
||||
bi = yaffs_get_block_info(dev, blk);
|
||||
- state = bi->block_state;
|
||||
+ state = (enum yaffs_block_state)(bi->block_state);
|
||||
|
||||
deleted = 0;
|
||||
|
||||
@@ -95,7 +95,7 @@ int yaffs1_scan(struct yaffs_dev *dev)
|
||||
/* Read the tags and decide what to do */
|
||||
chunk = blk * dev->param.chunks_per_block + c;
|
||||
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL,
|
||||
+ yaffs_rd_chunk_tags_nand(dev, chunk, NULL,
|
||||
&tags);
|
||||
|
||||
/* Let's have a good look at this chunk... */
|
||||
@@ -181,7 +181,7 @@ int yaffs1_scan(struct yaffs_dev *dev)
|
||||
yaffs_set_chunk_bit(dev, blk, c);
|
||||
bi->pages_in_use++;
|
||||
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, chunk,
|
||||
+ yaffs_rd_chunk_tags_nand(dev, chunk,
|
||||
chunk_data,
|
||||
NULL);
|
||||
|
||||
diff --git a/yaffs/yaffs_yaffs2.c b/yaffs/yaffs_yaffs2.c
|
||||
index 5761e96..69acd20 100644
|
||||
--- a/yaffs/yaffs_yaffs2.c
|
||||
+++ b/yaffs/yaffs_yaffs2.c
|
||||
@@ -946,7 +946,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
|
||||
int is_shrink;
|
||||
int is_unlinked;
|
||||
struct yaffs_ext_tags tags;
|
||||
- int result;
|
||||
+ //int result;
|
||||
int alloc_failed = 0;
|
||||
int chunk = blk * dev->param.chunks_per_block + chunk_in_block;
|
||||
struct yaffs_file_var *file_var;
|
||||
@@ -954,12 +954,12 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
|
||||
struct yaffs_symlink_var *sl_var;
|
||||
|
||||
if (summary_available) {
|
||||
- result = yaffs_summary_fetch(dev, &tags, chunk_in_block);
|
||||
+ yaffs_summary_fetch(dev, &tags, chunk_in_block);
|
||||
tags.seq_number = bi->seq_number;
|
||||
}
|
||||
|
||||
if (!summary_available || tags.obj_id == 0) {
|
||||
- result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
|
||||
+ yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
|
||||
dev->tags_used++;
|
||||
} else {
|
||||
dev->summary_used++;
|
||||
@@ -1114,7 +1114,7 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
|
||||
* invalid data until needed.
|
||||
*/
|
||||
|
||||
- result = yaffs_rd_chunk_tags_nand(dev,
|
||||
+ yaffs_rd_chunk_tags_nand(dev,
|
||||
chunk,
|
||||
chunk_data,
|
||||
NULL);
|
||||
@@ -1349,7 +1349,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
|
||||
int n_to_scan = 0;
|
||||
enum yaffs_block_state state;
|
||||
int c;
|
||||
- int deleted;
|
||||
+ //int deleted;
|
||||
LIST_HEAD(hard_list);
|
||||
struct yaffs_block_info *bi;
|
||||
u32 seq_number;
|
||||
@@ -1467,7 +1467,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
|
||||
/* get the block to scan in the correct order */
|
||||
blk = block_index[block_iter].block;
|
||||
bi = yaffs_get_block_info(dev, blk);
|
||||
- deleted = 0;
|
||||
+ //deleted = 0;
|
||||
|
||||
summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
|
||||
|
||||
diff --git a/yaffs_osglue.c b/yaffs_osglue.c
|
||||
index 2c34f99..4f2e5db 100644
|
||||
--- a/yaffs_osglue.c
|
||||
+++ b/yaffs_osglue.c
|
||||
@@ -58,7 +58,6 @@ void yaffsfs_LockInit(void)
|
||||
#else
|
||||
|
||||
static rt_mutex_t mutex = RT_NULL;
|
||||
-static rt_sem_t sem = RT_NULL;
|
||||
void yaffsfs_Lock(void)
|
||||
{
|
||||
rt_mutex_take(mutex, RT_WAITING_FOREVER);
|
||||
@@ -1,46 +0,0 @@
|
||||
how to use yaffs under rt-thread.
|
||||
|
||||
There are three steps.
|
||||
1. get yaffs tarball from official repo.
|
||||
the repo of official repo is here.
|
||||
http://www.aleph1.co.uk/gitweb?p=yaffs2.git;a=summary
|
||||
then you should find the 2011-6-28's snapshot, download the tarball
|
||||
http://www.aleph1.co.uk/gitweb?p=yaffs2.git;a=snapshot;h=2df51cdb98e799c4d10b4cc7dd7e8858aa79e7d8;sf=tgz
|
||||
|
||||
decompress the yaffs.tar.gz to rt-thread\components\dfs\filesystems\yaffs2\yaffs
|
||||
|
||||
2. patch yaffs.diff
|
||||
open an terminal.
|
||||
(1) on windows
|
||||
open cmd command prompt, then use [cd] command to come current path
|
||||
for example
|
||||
F:\Project\svn\rt-thread\components\dfs\filesystems\yaffs2>
|
||||
then type command
|
||||
patch -p1 < yaffs.diff
|
||||
|
||||
you will get some log information as followings
|
||||
F:\Project\svn\rt-thread\components\dfs\filesystems\yaffs2>patch -p1 < yaffs.diff
|
||||
patching file `dfs_yaffs2.c'
|
||||
patching file `yaffs/direct/yaffs_list.h'
|
||||
patching file `yaffs/direct/yaffs_nandif.c'
|
||||
patching file `yaffs/direct/ydirectenv.h'
|
||||
patching file `yaffs/direct/yportenv.h'
|
||||
patching file `yaffs_nandcfg.c'
|
||||
patching file `yaffs_osglue.c'
|
||||
|
||||
now you can delete yaffs.diff
|
||||
there is another patch file, as the name shows, it is to fix compile
|
||||
warning, so it is not necessary. If you want, you can use the
|
||||
following command.
|
||||
patch -p1 < fixwarning.diff
|
||||
|
||||
(2) on linux
|
||||
Help yourself. Since you have use linux as your os, I believe in you.
|
||||
|
||||
3.add nand driver and compile
|
||||
In order to use yaffs, you should provide a nand driver which is needed
|
||||
by yaffs. There is an example file in rt-thread\components\dfs\filesystems\uffs\nand.
|
||||
you should modify yaffs_nandcfg.c according to your nand driver.
|
||||
then you can use scons or IDE like MDK or IAR to compile.
|
||||
|
||||
enjoy !
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
src/ - The source code for the lwIP TCP/IP stack.
|
||||
doc/ - The documentation for lwIP.
|
||||
|
||||
See also the FILES file in each subdirectory.
|
||||
@@ -1,89 +0,0 @@
|
||||
INTRODUCTION
|
||||
|
||||
lwIP is a small independent implementation of the TCP/IP protocol
|
||||
suite that has been developed by Adam Dunkels at the Computer and
|
||||
Networks Architectures (CNA) lab at the Swedish Institute of Computer
|
||||
Science (SICS).
|
||||
|
||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
||||
while still having a full scale TCP. This making lwIP suitable for use
|
||||
in embedded systems with tens of kilobytes of free RAM and room for
|
||||
around 40 kilobytes of code ROM.
|
||||
|
||||
FEATURES
|
||||
|
||||
* IP (Internet Protocol) including packet forwarding over multiple network
|
||||
interfaces
|
||||
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
|
||||
* IGMP (Internet Group Management Protocol) for multicast traffic management
|
||||
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
|
||||
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
|
||||
and fast recovery/fast retransmit
|
||||
* Specialized raw/native API for enhanced performance
|
||||
* Optional Berkeley-like socket API
|
||||
* DNS (Domain names resolver)
|
||||
* SNMP (Simple Network Management Protocol)
|
||||
* DHCP (Dynamic Host Configuration Protocol)
|
||||
* AUTOIP (for IPv4, conform with RFC 3927)
|
||||
* PPP (Point-to-Point Protocol)
|
||||
* ARP (Address Resolution Protocol) for Ethernet
|
||||
|
||||
LICENSE
|
||||
|
||||
lwIP is freely available under a BSD license.
|
||||
|
||||
DEVELOPMENT
|
||||
|
||||
lwIP has grown into an excellent TCP/IP stack for embedded devices,
|
||||
and developers using the stack often submit bug fixes, improvements,
|
||||
and additions to the stack to further increase its usefulness.
|
||||
|
||||
Development of lwIP is hosted on Savannah, a central point for
|
||||
software development, maintenance and distribution. Everyone can
|
||||
help improve lwIP by use of Savannah's interface, CVS and the
|
||||
mailing list. A core team of developers will commit changes to the
|
||||
CVS source tree.
|
||||
|
||||
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
||||
contributions (such as platform ports) are in the 'contrib' module.
|
||||
|
||||
See doc/savannah.txt for details on CVS server access for users and
|
||||
developers.
|
||||
|
||||
Last night's CVS tar ball can be downloaded from:
|
||||
http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING]
|
||||
|
||||
The current CVS trees are web-browsable:
|
||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/
|
||||
|
||||
Submit patches and bugs via the lwIP project page:
|
||||
http://savannah.nongnu.org/projects/lwip/
|
||||
|
||||
|
||||
DOCUMENTATION
|
||||
|
||||
The original out-dated homepage of lwIP and Adam Dunkels' papers on
|
||||
lwIP are at the official lwIP home page:
|
||||
http://www.sics.se/~adam/lwip/
|
||||
|
||||
Self documentation of the source code is regularly extracted from the
|
||||
current CVS sources and is available from this web page:
|
||||
http://www.nongnu.org/lwip/
|
||||
|
||||
There is now a constantly growin wiki about lwIP at
|
||||
http://lwip.wikia.com/wiki/LwIP_Wiki
|
||||
|
||||
Also, there are mailing lists you can subscribe at
|
||||
http://savannah.nongnu.org/mail/?group=lwip
|
||||
plus searchable archives:
|
||||
http://lists.nongnu.org/archive/html/lwip-users/
|
||||
http://lists.nongnu.org/archive/html/lwip-devel/
|
||||
|
||||
Reading Adam's papers, the files in docs/, browsing the source code
|
||||
documentation and browsing the mailing list archives is a good way to
|
||||
become familiar with the design of lwIP.
|
||||
|
||||
Adam Dunkels <adam@sics.se>
|
||||
Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
src = Split("""
|
||||
src/api/api_lib.c
|
||||
src/api/api_msg.c
|
||||
src/api/err.c
|
||||
src/api/netbuf.c
|
||||
src/api/netdb.c
|
||||
src/api/netifapi.c
|
||||
src/api/sockets.c
|
||||
src/api/tcpip.c
|
||||
src/arch/sys_arch.c
|
||||
src/arch/sys_arch_init.c
|
||||
src/core/dhcp.c
|
||||
src/core/dns.c
|
||||
src/core/init.c
|
||||
src/core/memp.c
|
||||
src/core/netif.c
|
||||
src/core/pbuf.c
|
||||
src/core/raw.c
|
||||
src/core/stats.c
|
||||
src/core/sys.c
|
||||
src/core/tcp.c
|
||||
src/core/tcp_in.c
|
||||
src/core/tcp_out.c
|
||||
src/core/udp.c
|
||||
src/core/ipv4/autoip.c
|
||||
src/core/ipv4/icmp.c
|
||||
src/core/ipv4/igmp.c
|
||||
src/core/ipv4/inet.c
|
||||
src/core/ipv4/inet_chksum.c
|
||||
src/core/ipv4/ip.c
|
||||
src/core/ipv4/ip_addr.c
|
||||
src/core/ipv4/ip_frag.c
|
||||
src/netif/etharp.c
|
||||
src/netif/ethernetif.c
|
||||
src/netif/loopif.c
|
||||
src/netif/slipif.c
|
||||
""")
|
||||
|
||||
snmp_src = Split("""
|
||||
src/core/snmp/asn1_dec.c
|
||||
src/core/snmp/asn1_enc.c
|
||||
src/core/snmp/mib2.c
|
||||
src/core/snmp/mib_structs.c
|
||||
src/core/snmp/msg_in.c
|
||||
src/core/snmp/msg_out.c
|
||||
""")
|
||||
|
||||
ppp_src = Split("""
|
||||
src/netif/ppp/auth.c
|
||||
src/netif/ppp/chap.c
|
||||
src/netif/ppp/chpms.c
|
||||
src/netif/ppp/fsm.c
|
||||
src/netif/ppp/ipcp.c
|
||||
src/netif/ppp/lcp.c
|
||||
src/netif/ppp/magic.c
|
||||
src/netif/ppp/md5.c
|
||||
src/netif/ppp/pap.c
|
||||
src/netif/ppp/ppp.c
|
||||
src/netif/ppp/ppp_oe.c
|
||||
src/netif/ppp/randm.c
|
||||
src/netif/ppp/vj.c
|
||||
""")
|
||||
|
||||
# The set of source files associated with this SConscript file.
|
||||
path = [GetCurrentDir() + '/src',
|
||||
GetCurrentDir() + '/src/include',
|
||||
GetCurrentDir() + '/src/include/ipv4',
|
||||
GetCurrentDir() + '/src/arch/include',
|
||||
GetCurrentDir() + '/src/include/netif']
|
||||
|
||||
if GetDepend(['RT_LWIP_SNMP']):
|
||||
src += snmp_src
|
||||
|
||||
if GetDepend(['RT_LWIP_PPP']):
|
||||
src += ppp_src
|
||||
path += [GetCurrentDir() + '/src/netif/ppp']
|
||||
|
||||
# For testing apps
|
||||
if GetDepend(['RT_USING_NETUTILS']):
|
||||
src += Glob('./apps/*.c')
|
||||
|
||||
group = DefineGroup('LwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP132'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
||||
@@ -1,216 +0,0 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#define MAX_SERV 32 /* Maximum number of chargen services. Don't need too many */
|
||||
#define CHARGEN_THREAD_NAME "chargen"
|
||||
#if RT_THREAD_PRIORITY_MAX == 32
|
||||
#define CHARGEN_PRIORITY 20 /* Really low priority */
|
||||
#else
|
||||
#define CHARGEN_PRIORITY 200 /* Really low priority */
|
||||
#endif
|
||||
#define CHARGEN_THREAD_STACKSIZE 1024
|
||||
struct charcb
|
||||
{
|
||||
struct charcb *next;
|
||||
int socket;
|
||||
struct sockaddr_in cliaddr;
|
||||
socklen_t clilen;
|
||||
char nextchar;
|
||||
};
|
||||
|
||||
static struct charcb *charcb_list = 0;
|
||||
static int do_read(struct charcb *p_charcb);
|
||||
static void close_chargen(struct charcb *p_charcb);
|
||||
|
||||
/**************************************************************
|
||||
* void chargen_thread(void *arg)
|
||||
*
|
||||
* chargen task. This server will wait for connections on well
|
||||
* known TCP port number: 19. For every connection, the server will
|
||||
* write as much data as possible to the tcp port.
|
||||
**************************************************************/
|
||||
static void chargen_thread(void *arg)
|
||||
{
|
||||
int listenfd;
|
||||
struct sockaddr_in chargen_saddr;
|
||||
fd_set readset;
|
||||
fd_set writeset;
|
||||
int i, maxfdp1;
|
||||
struct charcb *p_charcb;
|
||||
|
||||
/* First acquire our socket for listening for connections */
|
||||
listenfd = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
LWIP_ASSERT("chargen_thread(): Socket create failed.", listenfd >= 0);
|
||||
memset(&chargen_saddr, 0, sizeof(chargen_saddr));
|
||||
chargen_saddr.sin_family = AF_INET;
|
||||
chargen_saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
chargen_saddr.sin_port = htons(19); // Chargen server port
|
||||
|
||||
if (lwip_bind(listenfd, (struct sockaddr *) &chargen_saddr, sizeof(chargen_saddr)) == -1)
|
||||
LWIP_ASSERT("chargen_thread(): Socket bind failed.", 0);
|
||||
|
||||
/* Put socket into listening mode */
|
||||
if (lwip_listen(listenfd, MAX_SERV) == -1)
|
||||
LWIP_ASSERT("chargen_thread(): Listen failed.", 0);
|
||||
|
||||
/* Wait forever for network input: This could be connections or data */
|
||||
for (;;)
|
||||
{
|
||||
maxfdp1 = listenfd+1;
|
||||
|
||||
/* Determine what sockets need to be in readset */
|
||||
FD_ZERO(&readset);
|
||||
FD_ZERO(&writeset);
|
||||
FD_SET(listenfd, &readset);
|
||||
for (p_charcb = charcb_list; p_charcb; p_charcb = p_charcb->next)
|
||||
{
|
||||
if (maxfdp1 < p_charcb->socket + 1)
|
||||
maxfdp1 = p_charcb->socket + 1;
|
||||
FD_SET(p_charcb->socket, &readset);
|
||||
FD_SET(p_charcb->socket, &writeset);
|
||||
}
|
||||
|
||||
/* Wait for data or a new connection */
|
||||
i = lwip_select(maxfdp1, &readset, &writeset, 0, 0);
|
||||
|
||||
if (i == 0) continue;
|
||||
|
||||
/* At least one descriptor is ready */
|
||||
if (FD_ISSET(listenfd, &readset))
|
||||
{
|
||||
/* We have a new connection request!!! */
|
||||
/* Lets create a new control block */
|
||||
p_charcb = (struct charcb *)rt_calloc(1, sizeof(struct charcb));
|
||||
if (p_charcb)
|
||||
{
|
||||
p_charcb->socket = lwip_accept(listenfd,
|
||||
(struct sockaddr *) &p_charcb->cliaddr,
|
||||
&p_charcb->clilen);
|
||||
if (p_charcb->socket < 0)
|
||||
rt_free(p_charcb);
|
||||
else
|
||||
{
|
||||
/* Keep this tecb in our list */
|
||||
p_charcb->next = charcb_list;
|
||||
charcb_list = p_charcb;
|
||||
p_charcb->nextchar = 0x21;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No memory to accept connection. Just accept and then close */
|
||||
int sock;
|
||||
struct sockaddr cliaddr;
|
||||
socklen_t clilen;
|
||||
|
||||
sock = lwip_accept(listenfd, &cliaddr, &clilen);
|
||||
if (sock >= 0)
|
||||
lwip_close(sock);
|
||||
}
|
||||
}
|
||||
/* Go through list of connected clients and process data */
|
||||
for (p_charcb = charcb_list; p_charcb; p_charcb = p_charcb->next)
|
||||
{
|
||||
if (FD_ISSET(p_charcb->socket, &readset))
|
||||
{
|
||||
/* This socket is ready for reading. This could be because someone typed
|
||||
* some characters or it could be because the socket is now closed. Try reading
|
||||
* some data to see. */
|
||||
if (do_read(p_charcb) < 0)
|
||||
break;
|
||||
}
|
||||
if (FD_ISSET(p_charcb->socket, &writeset))
|
||||
{
|
||||
char line[80];
|
||||
char setchar = p_charcb->nextchar;
|
||||
|
||||
for( i = 0; i < 59; i++)
|
||||
{
|
||||
line[i] = setchar;
|
||||
if (++setchar == 0x7f)
|
||||
setchar = 0x21;
|
||||
}
|
||||
line[i] = 0;
|
||||
strcat(line, "\n\r");
|
||||
if (lwip_write(p_charcb->socket, line, strlen(line)) < 0)
|
||||
{
|
||||
close_chargen(p_charcb);
|
||||
break;
|
||||
}
|
||||
if (++p_charcb->nextchar == 0x7f)
|
||||
p_charcb->nextchar = 0x21;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* void close_chargen(struct charcb *p_charcb)
|
||||
*
|
||||
* Close the socket and remove this charcb from the list.
|
||||
**************************************************************/
|
||||
static void close_chargen(struct charcb *p_charcb)
|
||||
{
|
||||
struct charcb *p_search_charcb;
|
||||
|
||||
/* Either an error or tcp connection closed on other
|
||||
* end. Close here */
|
||||
lwip_close(p_charcb->socket);
|
||||
|
||||
/* Free charcb */
|
||||
if (charcb_list == p_charcb)
|
||||
charcb_list = p_charcb->next;
|
||||
else
|
||||
for (p_search_charcb = charcb_list; p_search_charcb; p_search_charcb = p_search_charcb->next)
|
||||
{
|
||||
if (p_search_charcb->next == p_charcb)
|
||||
{
|
||||
p_search_charcb->next = p_charcb->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rt_free(p_charcb);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* void do_read(struct charcb *p_charcb)
|
||||
*
|
||||
* Socket definitely is ready for reading. Read a buffer from the socket and
|
||||
* discard the data. If no data is read, then the socket is closed and the
|
||||
* charcb is removed from the list and freed.
|
||||
**************************************************************/
|
||||
static int do_read(struct charcb *p_charcb)
|
||||
{
|
||||
char buffer[80];
|
||||
int readcount;
|
||||
|
||||
/* Read some data */
|
||||
readcount = lwip_read(p_charcb->socket, &buffer, 80);
|
||||
if (readcount <= 0)
|
||||
{
|
||||
close_chargen(p_charcb);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chargen_init(void)
|
||||
{
|
||||
rt_thread_t chargen;
|
||||
|
||||
chargen = rt_thread_create(CHARGEN_THREAD_NAME,
|
||||
chargen_thread, RT_NULL,
|
||||
CHARGEN_THREAD_STACKSIZE,
|
||||
CHARGEN_PRIORITY, 5);
|
||||
if (chargen != RT_NULL) rt_thread_startup(chargen);
|
||||
}
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
void chargen()
|
||||
{
|
||||
chargen_init();
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(chargen, start chargen server);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,376 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* MetIO Server
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*/
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_TCP
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
/*
|
||||
* This implements a netio server.
|
||||
* The client sends a command word (4 bytes) then a data length word (4 bytes).
|
||||
* If the command is "receive", the server is to consume "data length" bytes into
|
||||
* a circular buffer until the first byte is non-zero, then it is to consume
|
||||
* another command/data pair.
|
||||
* If the command is "send", the server is to send "data length" bytes from a circular
|
||||
* buffer with the first byte being zero, until "some time" (6 seconds in the
|
||||
* current netio126.zip download) has passed and then send one final buffer with
|
||||
* the first byte being non-zero. Then it is to consume another command/data pair.
|
||||
*/
|
||||
|
||||
/* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */
|
||||
|
||||
/* implementation options */
|
||||
#define NETIO_BUF_SIZE (4 * 1024)
|
||||
#define NETIO_USE_STATIC_BUF 0
|
||||
|
||||
/* NetIO server state definition */
|
||||
#define NETIO_STATE_WAIT_FOR_CMD 0
|
||||
#define NETIO_STATE_RECV_DATA 1
|
||||
#define NETIO_STATE_SEND_DATA 2
|
||||
#define NETIO_STATE_SEND_DATA_LAST 3
|
||||
#define NETIO_STATE_DONE 4
|
||||
|
||||
struct netio_state {
|
||||
u32_t state;
|
||||
u32_t cmd;
|
||||
u32_t data_len;
|
||||
u32_t cntr;
|
||||
u8_t * buf_ptr;
|
||||
u32_t buf_pos;
|
||||
u32_t first_byte;
|
||||
u32_t time_stamp;
|
||||
};
|
||||
|
||||
/* NetIO command protocol definition */
|
||||
#define NETIO_CMD_QUIT 0
|
||||
#define NETIO_CMD_C2S 1
|
||||
#define NETIO_CMD_S2C 2
|
||||
#define NETIO_CMD_RES 3
|
||||
|
||||
static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
|
||||
static void
|
||||
netio_close(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
err_t err;
|
||||
|
||||
struct netio_state *ns = arg;
|
||||
ns->state = NETIO_STATE_DONE;
|
||||
tcp_recv(pcb, NULL);
|
||||
err = tcp_close(pcb);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
/* closing failed, try again later */
|
||||
tcp_recv(pcb, netio_recv);
|
||||
} else {
|
||||
/* closing succeeded */
|
||||
#if NETIO_USE_STATIC_BUF != 1
|
||||
if(ns->buf_ptr != NULL){
|
||||
mem_free(ns->buf_ptr);
|
||||
}
|
||||
#endif
|
||||
tcp_arg(pcb, NULL);
|
||||
tcp_poll(pcb, NULL, 0);
|
||||
tcp_sent(pcb, NULL);
|
||||
if (arg != NULL) {
|
||||
mem_free(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static err_t
|
||||
netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
struct netio_state *ns = arg;
|
||||
u8_t * data_ptr;
|
||||
u32_t data_cntr;
|
||||
struct pbuf *q = p;
|
||||
u16_t len;
|
||||
|
||||
if (p != NULL) {
|
||||
tcp_recved(pcb, p->tot_len);
|
||||
}
|
||||
|
||||
if (err == ERR_OK && q != NULL) {
|
||||
|
||||
while (q != NULL) {
|
||||
data_cntr = q->len;
|
||||
data_ptr = q->payload;
|
||||
while (data_cntr--) {
|
||||
if (ns->state == NETIO_STATE_DONE){
|
||||
netio_close(ns, pcb);
|
||||
break;
|
||||
} else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) {
|
||||
if (ns->cntr < 4) {
|
||||
/* build up the CMD field */
|
||||
ns->cmd <<= 8;
|
||||
ns->cmd |= *data_ptr++;
|
||||
ns->cntr++;
|
||||
} else if (ns->cntr < 8) {
|
||||
/* build up the DATA field */
|
||||
ns->data_len <<= 8;
|
||||
ns->data_len |= *data_ptr++;
|
||||
ns->cntr++;
|
||||
|
||||
if (ns->cntr == 8) {
|
||||
/* now we have full command and data words */
|
||||
ns->cntr = 0;
|
||||
ns->buf_pos = 0;
|
||||
ns->buf_ptr[0] = 0;
|
||||
if (ns->cmd == NETIO_CMD_C2S) {
|
||||
ns->state = NETIO_STATE_RECV_DATA;
|
||||
} else if (ns->cmd == NETIO_CMD_S2C) {
|
||||
ns->state = NETIO_STATE_SEND_DATA;
|
||||
/* start timer */
|
||||
ns->time_stamp = rt_tick_get();
|
||||
/* send first round of data */
|
||||
|
||||
len = tcp_sndbuf(pcb);
|
||||
len = LWIP_MIN(len, ns->data_len - ns->cntr);
|
||||
len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos);
|
||||
|
||||
do {
|
||||
err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY);
|
||||
if (err == ERR_MEM) {
|
||||
len /= 2;
|
||||
}
|
||||
} while ((err == ERR_MEM) && (len > 1));
|
||||
|
||||
ns->buf_pos += len;
|
||||
ns->cntr += len;
|
||||
|
||||
} else {
|
||||
/* unrecognized command, punt */
|
||||
ns->cntr = 0;
|
||||
ns->buf_pos = 0;
|
||||
ns->buf_ptr[0] = 0;
|
||||
netio_close(ns, pcb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* in trouble... shouldn't be in this state! */
|
||||
}
|
||||
|
||||
} else if (ns->state == NETIO_STATE_RECV_DATA) {
|
||||
int chunk_length;
|
||||
|
||||
if(ns->cntr == 0){
|
||||
/* save the first byte of this new round of data
|
||||
* this will not match ns->buf_ptr[0] in the case that
|
||||
* NETIO_BUF_SIZE is less than ns->data_len.
|
||||
*/
|
||||
ns->first_byte = *data_ptr;
|
||||
}
|
||||
|
||||
if (ns->cntr + (data_cntr + 1) < ns->data_len) chunk_length = data_cntr + 1;
|
||||
else chunk_length = (ns->data_len - ns->cntr);
|
||||
|
||||
ns->buf_pos += chunk_length;
|
||||
data_ptr += chunk_length;
|
||||
ns->cntr += chunk_length;
|
||||
data_cntr -= (chunk_length - 1);
|
||||
|
||||
if (ns->buf_pos >= NETIO_BUF_SIZE) {
|
||||
/* circularize the buffer */
|
||||
ns->buf_pos %= NETIO_BUF_SIZE;
|
||||
}
|
||||
|
||||
if(ns->cntr == ns->data_len){
|
||||
ns->cntr = 0;
|
||||
if (ns->first_byte != 0) {
|
||||
/* if this last round did not start with 0,
|
||||
* go look for another command */
|
||||
ns->state = NETIO_STATE_WAIT_FOR_CMD;
|
||||
ns->data_len = 0;
|
||||
ns->cmd = 0;
|
||||
/* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */
|
||||
} else {
|
||||
/* stay here and wait on more data */
|
||||
}
|
||||
}
|
||||
|
||||
} else if (ns->state == NETIO_STATE_SEND_DATA
|
||||
|| ns->state == NETIO_STATE_SEND_DATA_LAST) {
|
||||
/* I don't think this should happen... */
|
||||
} else {
|
||||
/* done / quit */
|
||||
netio_close(ns, pcb);
|
||||
break;
|
||||
} /* end of ns->state condition */
|
||||
} /* end of while data still in this pbuf */
|
||||
|
||||
q = q->next;
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
} else {
|
||||
|
||||
/* error or closed by other side */
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/* close the connection */
|
||||
netio_close(ns, pcb);
|
||||
|
||||
}
|
||||
return ERR_OK;
|
||||
|
||||
}
|
||||
|
||||
static err_t
|
||||
netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
struct netio_state *ns = arg;
|
||||
err_t err = ERR_OK;
|
||||
|
||||
if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) {
|
||||
/* done with this round of sending */
|
||||
ns->buf_pos = 0;
|
||||
ns->cntr = 0;
|
||||
|
||||
/* check if timer expired */
|
||||
if (rt_tick_get() - ns->time_stamp > 600) {
|
||||
ns->buf_ptr[0] = 1;
|
||||
ns->state = NETIO_STATE_SEND_DATA_LAST;
|
||||
} else {
|
||||
ns->buf_ptr[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){
|
||||
len = tcp_sndbuf(pcb);
|
||||
len = LWIP_MIN(len, ns->data_len - ns->cntr);
|
||||
len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos);
|
||||
|
||||
if(ns->cntr < ns->data_len){
|
||||
do {
|
||||
err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY);
|
||||
if (err == ERR_MEM) {
|
||||
len /= 2;
|
||||
}
|
||||
} while ((err == ERR_MEM) && (len > 1));
|
||||
|
||||
ns->buf_pos += len;
|
||||
if(ns->buf_pos >= NETIO_BUF_SIZE){
|
||||
ns->buf_pos = 0;
|
||||
}
|
||||
|
||||
ns->cntr += len;
|
||||
}
|
||||
}
|
||||
|
||||
if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){
|
||||
/* we have buffered up all our data to send this last round, go look for a command */
|
||||
ns->state = NETIO_STATE_WAIT_FOR_CMD;
|
||||
ns->cntr = 0;
|
||||
/* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
netio_poll(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
struct netio_state * ns = arg;
|
||||
if(ns->state == NETIO_STATE_SEND_DATA){
|
||||
|
||||
} else if(ns->state == NETIO_STATE_DONE){
|
||||
netio_close(ns, pcb);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
|
||||
}
|
||||
|
||||
#if NETIO_USE_STATIC_BUF == 1
|
||||
static u8_t netio_buf[NETIO_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
static err_t
|
||||
netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
||||
{
|
||||
struct netio_state * ns;
|
||||
|
||||
LWIP_UNUSED_ARG(err);
|
||||
|
||||
ns = mem_malloc(sizeof(struct netio_state));
|
||||
|
||||
if(ns == NULL){
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ns->state = NETIO_STATE_WAIT_FOR_CMD;
|
||||
ns->data_len = 0;
|
||||
ns->cmd = 0;
|
||||
ns->cntr = 0;
|
||||
ns->buf_pos = 0;
|
||||
#if NETIO_USE_STATIC_BUF == 1
|
||||
ns->buf_ptr = netio_buf;
|
||||
#else
|
||||
ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE);
|
||||
|
||||
if(ns->buf_ptr == NULL){
|
||||
mem_free(ns);
|
||||
return ERR_MEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
ns->buf_ptr[0] = 0;
|
||||
|
||||
tcp_arg(pcb, ns);
|
||||
tcp_sent(pcb, netio_sent);
|
||||
tcp_recv(pcb, netio_recv);
|
||||
tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void netio_init(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
|
||||
pcb = tcp_new();
|
||||
tcp_bind(pcb, IP_ADDR_ANY, 18767);
|
||||
pcb = tcp_listen(pcb);
|
||||
tcp_accept(pcb, netio_accept);
|
||||
}
|
||||
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
FINSH_FUNCTION_EXPORT(netio_init, netio server);
|
||||
#endif
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* netutils: ping implementation
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
/**
|
||||
* PING_DEBUG: Enable debugging for PING.
|
||||
*/
|
||||
#ifndef PING_DEBUG
|
||||
#define PING_DEBUG LWIP_DBG_ON
|
||||
#endif
|
||||
|
||||
/** ping receive timeout - in milliseconds */
|
||||
#define PING_RCV_TIMEO 1000
|
||||
/** ping delay - in milliseconds */
|
||||
#define PING_DELAY 100
|
||||
|
||||
/** ping identifier - must fit on a u16_t */
|
||||
#ifndef PING_ID
|
||||
#define PING_ID 0xAFAF
|
||||
#endif
|
||||
|
||||
/** ping additional data size to include in the packet */
|
||||
#ifndef PING_DATA_SIZE
|
||||
#define PING_DATA_SIZE 32
|
||||
#endif
|
||||
|
||||
/* ping variables */
|
||||
static u16_t ping_seq_num;
|
||||
struct _ip_addr
|
||||
{
|
||||
rt_uint8_t addr0, addr1, addr2, addr3;
|
||||
};
|
||||
|
||||
/** Prepare a echo ICMP request */
|
||||
static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
|
||||
{
|
||||
size_t i;
|
||||
size_t data_len = len - sizeof(struct icmp_echo_hdr);
|
||||
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
|
||||
ICMPH_CODE_SET(iecho, 0);
|
||||
iecho->chksum = 0;
|
||||
iecho->id = PING_ID;
|
||||
iecho->seqno = htons(++ping_seq_num);
|
||||
|
||||
/* fill the additional data buffer with some data */
|
||||
for(i = 0; i < data_len; i++)
|
||||
{
|
||||
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
|
||||
}
|
||||
|
||||
iecho->chksum = inet_chksum(iecho, len);
|
||||
}
|
||||
|
||||
/* Ping using the socket ip */
|
||||
static err_t ping_send(int s, struct ip_addr *addr, int size)
|
||||
{
|
||||
int err;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct sockaddr_in to;
|
||||
size_t ping_size = sizeof(struct icmp_echo_hdr) + size;
|
||||
LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
|
||||
|
||||
iecho = rt_malloc(ping_size);
|
||||
if (iecho == RT_NULL)
|
||||
{
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ping_prepare_echo(iecho, (u16_t)ping_size);
|
||||
|
||||
to.sin_len = sizeof(to);
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_addr.s_addr = addr->addr;
|
||||
|
||||
err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
|
||||
rt_free(iecho);
|
||||
|
||||
return (err ? ERR_OK : ERR_VAL);
|
||||
}
|
||||
|
||||
static void ping_recv(int s)
|
||||
{
|
||||
char buf[64];
|
||||
int fromlen, len;
|
||||
struct sockaddr_in from;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct _ip_addr *addr;
|
||||
|
||||
while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0)
|
||||
{
|
||||
if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr)))
|
||||
{
|
||||
addr = (struct _ip_addr *)&(from.sin_addr);
|
||||
rt_kprintf("ping: recv %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
|
||||
iphdr = (struct ip_hdr *)buf;
|
||||
iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
|
||||
if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("ping: drop\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
{
|
||||
rt_kprintf("ping: timeout\n");
|
||||
}
|
||||
}
|
||||
|
||||
rt_err_t ping(char* target, rt_uint32_t time, rt_size_t size)
|
||||
{
|
||||
int s;
|
||||
int timeout = PING_RCV_TIMEO;
|
||||
struct ip_addr ping_target;
|
||||
rt_uint32_t send_time;
|
||||
struct _ip_addr
|
||||
{
|
||||
rt_uint8_t addr0, addr1, addr2, addr3;
|
||||
} *addr;
|
||||
|
||||
send_time = 0;
|
||||
|
||||
if(size == 0)
|
||||
size = PING_DATA_SIZE;
|
||||
|
||||
if (inet_aton(target, (struct in_addr*)&ping_target) == 0) return -RT_ERROR;
|
||||
addr = (struct _ip_addr*)&ping_target;
|
||||
|
||||
if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
|
||||
{
|
||||
rt_kprintf("create socket failled\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (ping_send(s, &ping_target, size) == ERR_OK)
|
||||
{
|
||||
rt_kprintf("ping: send %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
ping_recv(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("ping: send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
}
|
||||
|
||||
send_time ++;
|
||||
if (send_time >= time) break; /* send ping times reached, stop */
|
||||
|
||||
rt_thread_delay(PING_DELAY); /* take a delay */
|
||||
}
|
||||
|
||||
lwip_close(s);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
FINSH_FUNCTION_EXPORT(ping, ping network host);
|
||||
#endif
|
||||
@@ -1,213 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* SNTP client module
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
/** This is an example of a "SNTP" client (with socket API).
|
||||
*
|
||||
* For a list of some public NTP servers, see this link :
|
||||
* http://support.ntp.org/bin/view/Servers/NTPPoolServers
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SNTP_DEBUG: Enable debugging for SNTP.
|
||||
*/
|
||||
#ifndef SNTP_DEBUG
|
||||
#define SNTP_DEBUG LWIP_DBG_ON
|
||||
#endif
|
||||
|
||||
/** SNTP server port */
|
||||
#ifndef SNTP_PORT
|
||||
#define SNTP_PORT 123
|
||||
#endif
|
||||
|
||||
/** SNTP server address as IPv4 address in "u32_t" format */
|
||||
#ifndef SNTP_SERVER_ADDRESS
|
||||
#define SNTP_SERVER_ADDRESS inet_addr("213.161.194.93") /* pool.ntp.org */
|
||||
#endif
|
||||
|
||||
/** SNTP receive timeout - in milliseconds */
|
||||
#ifndef SNTP_RECV_TIMEOUT
|
||||
#define SNTP_RECV_TIMEOUT 3000
|
||||
#endif
|
||||
|
||||
/** SNTP update delay - in milliseconds */
|
||||
#ifndef SNTP_UPDATE_DELAY
|
||||
#define SNTP_UPDATE_DELAY 60000
|
||||
#endif
|
||||
|
||||
/** SNTP macro to change system time and/or the update the RTC clock */
|
||||
#ifndef SNTP_SYSTEM_TIME
|
||||
#define SNTP_SYSTEM_TIME(t)
|
||||
#endif
|
||||
|
||||
/* SNTP protocol defines */
|
||||
#define SNTP_MAX_DATA_LEN 48
|
||||
#define SNTP_RCV_TIME_OFS 32
|
||||
#define SNTP_LI_NO_WARNING 0x00
|
||||
#define SNTP_VERSION (4/* NTP Version 4*/<<3)
|
||||
#define SNTP_MODE_CLIENT 0x03
|
||||
#define SNTP_MODE_SERVER 0x04
|
||||
#define SNTP_MODE_BROADCAST 0x05
|
||||
#define SNTP_MODE_MASK 0x07
|
||||
|
||||
/* number of seconds between 1900 and 1970 */
|
||||
#define DIFF_SEC_1900_1970 (2208988800)
|
||||
|
||||
/**
|
||||
* SNTP processing
|
||||
*/
|
||||
static void sntp_process( time_t t)
|
||||
{
|
||||
/* change system time and/or the update the RTC clock */
|
||||
SNTP_SYSTEM_TIME(t);
|
||||
|
||||
/* display local time from GMT time */
|
||||
LWIP_DEBUGF( SNTP_DEBUG, ("sntp_process: %s", ctime(&t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* SNTP request
|
||||
*/
|
||||
static void sntp_request()
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in local;
|
||||
struct sockaddr_in to;
|
||||
int tolen;
|
||||
int size;
|
||||
int timeout;
|
||||
u8_t sntp_request [SNTP_MAX_DATA_LEN];
|
||||
u8_t sntp_response[SNTP_MAX_DATA_LEN];
|
||||
u32_t sntp_server_address;
|
||||
u32_t timestamp;
|
||||
time_t t;
|
||||
|
||||
/* initialize SNTP server address */
|
||||
sntp_server_address = SNTP_SERVER_ADDRESS;
|
||||
|
||||
/* if we got a valid SNTP server address... */
|
||||
if (sntp_server_address!=0)
|
||||
{
|
||||
/* create new socket */
|
||||
sock = socket( AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock>=0)
|
||||
{
|
||||
/* prepare local address */
|
||||
memset(&local, 0, sizeof(local));
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_port = htons(INADDR_ANY);
|
||||
local.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
/* bind to local address */
|
||||
if (bind( sock, (struct sockaddr *)&local, sizeof(local))==0)
|
||||
{
|
||||
/* set recv timeout */
|
||||
timeout = SNTP_RECV_TIMEOUT;
|
||||
setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
|
||||
/* prepare SNTP request */
|
||||
memset( sntp_request, 0, sizeof(sntp_request));
|
||||
sntp_request[0] = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
|
||||
|
||||
/* prepare SNTP server address */
|
||||
memset(&to, 0, sizeof(to));
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_port = htons(SNTP_PORT);
|
||||
to.sin_addr.s_addr = sntp_server_address;
|
||||
|
||||
/* send SNTP request to server */
|
||||
if (sendto( sock, sntp_request, sizeof(sntp_request), 0, (struct sockaddr *)&to, sizeof(to))>=0)
|
||||
{
|
||||
/* receive SNTP server response */
|
||||
tolen = sizeof(to);
|
||||
size = recvfrom( sock, sntp_response, sizeof(sntp_response), 0, (struct sockaddr *)&to, (socklen_t *)&tolen);
|
||||
|
||||
/* if the response size is good */
|
||||
if (size == SNTP_MAX_DATA_LEN)
|
||||
{
|
||||
/* if this is a SNTP response... */
|
||||
if (((sntp_response[0] & SNTP_MODE_MASK) == SNTP_MODE_SERVER) || ((sntp_response[0] & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST))
|
||||
{
|
||||
/* extract GMT time from response */
|
||||
SMEMCPY( ×tamp, (sntp_response+SNTP_RCV_TIME_OFS), sizeof(timestamp));
|
||||
t = (ntohl(timestamp) - DIFF_SEC_1900_1970);
|
||||
|
||||
/* do time processing */
|
||||
sntp_process(t);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not response frame code\n"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not recvfrom==%i\n", errno));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not sendto==%i\n", errno));
|
||||
}
|
||||
}
|
||||
/* close the socket */
|
||||
closesocket(sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SNTP thread
|
||||
*/
|
||||
static void
|
||||
sntp_thread(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
while(1)
|
||||
{
|
||||
sntp_request();
|
||||
sys_msleep(SNTP_UPDATE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void sntp_init(void)
|
||||
{
|
||||
sys_thread_new("sntp_thread", sntp_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
#include <lwip/api.h>
|
||||
|
||||
#define TCP_ECHO_PORT 7
|
||||
|
||||
void tcpecho_entry(void *parameter)
|
||||
{
|
||||
struct netconn *conn, *newconn;
|
||||
err_t err;
|
||||
|
||||
/* Create a new connection identifier. */
|
||||
conn = netconn_new(NETCONN_TCP);
|
||||
|
||||
/* Bind connection to well known port number 7. */
|
||||
netconn_bind(conn, NULL, TCP_ECHO_PORT);
|
||||
|
||||
/* Tell connection to go into listening mode. */
|
||||
netconn_listen(conn);
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* Grab new connection. */
|
||||
newconn = netconn_accept(conn);
|
||||
/* Process the new connection. */
|
||||
if(newconn != NULL)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
void *data;
|
||||
u16_t len;
|
||||
|
||||
while((buf = netconn_recv(newconn)) != NULL)
|
||||
{
|
||||
do
|
||||
{
|
||||
netbuf_data(buf, &data, &len);
|
||||
err = netconn_write(newconn, data, len, NETCONN_COPY);
|
||||
if(err != ERR_OK){}
|
||||
}
|
||||
while(netbuf_next(buf) >= 0);
|
||||
netbuf_delete(buf);
|
||||
}
|
||||
/* Close connection and discard connection identifier. */
|
||||
netconn_delete(newconn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
static rt_thread_t echo_tid = RT_NULL;
|
||||
void tcpecho(rt_uint32_t startup)
|
||||
{
|
||||
if (startup && echo_tid == RT_NULL)
|
||||
{
|
||||
echo_tid = rt_thread_create("echo",
|
||||
tcpecho_entry, RT_NULL,
|
||||
512, 30, 5);
|
||||
if (echo_tid != RT_NULL)
|
||||
rt_thread_startup(echo_tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (echo_tid != RT_NULL)
|
||||
rt_thread_delete(echo_tid); /* delete thread */
|
||||
echo_tid = RT_NULL;
|
||||
}
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(tcpecho, startup or stop TCP echo server);
|
||||
#endif
|
||||
@@ -1,206 +0,0 @@
|
||||
#include <rtthread.h>
|
||||
#include <dfs_posix.h>
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
#define TFTP_PORT 69
|
||||
/* opcode */
|
||||
#define TFTP_RRQ 1 /* read request */
|
||||
#define TFTP_WRQ 2 /* write request */
|
||||
#define TFTP_DATA 3 /* data */
|
||||
#define TFTP_ACK 4 /* ACK */
|
||||
#define TFTP_ERROR 5 /* error */
|
||||
|
||||
rt_uint8_t tftp_buffer[512 + 4];
|
||||
/* tftp client */
|
||||
void tftp_get(const char* host, const char* dir, const char* filename)
|
||||
{
|
||||
int fd, sock_fd, sock_opt;
|
||||
struct sockaddr_in tftp_addr, from_addr;
|
||||
rt_uint32_t length;
|
||||
socklen_t fromlen;
|
||||
|
||||
/* make local file name */
|
||||
rt_snprintf((char*)tftp_buffer, sizeof(tftp_buffer),
|
||||
"%s/%s", dir, filename);
|
||||
|
||||
/* open local file for write */
|
||||
fd = open((char*)tftp_buffer, O_RDWR | O_CREAT, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
rt_kprintf("can't open local filename\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect to tftp server */
|
||||
inet_aton(host, (struct in_addr*)&(tftp_addr.sin_addr));
|
||||
tftp_addr.sin_family = AF_INET;
|
||||
tftp_addr.sin_port = htons(TFTP_PORT);
|
||||
|
||||
sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
||||
if (sock_fd < 0)
|
||||
{
|
||||
close(fd);
|
||||
rt_kprintf("can't create a socket\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
/* set socket option */
|
||||
sock_opt = 5000; /* 5 seconds */
|
||||
lwip_setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &sock_opt, sizeof(sock_opt));
|
||||
|
||||
/* make tftp request */
|
||||
tftp_buffer[0] = 0; /* opcode */
|
||||
tftp_buffer[1] = TFTP_RRQ; /* RRQ */
|
||||
length = rt_sprintf((char *)&tftp_buffer[2], "%s", filename) + 2;
|
||||
tftp_buffer[length] = 0; length ++;
|
||||
length += rt_sprintf((char*)&tftp_buffer[length], "%s", "octet");
|
||||
tftp_buffer[length] = 0; length ++;
|
||||
|
||||
fromlen = sizeof(struct sockaddr_in);
|
||||
|
||||
/* send request */
|
||||
lwip_sendto(sock_fd, tftp_buffer, length, 0,
|
||||
(struct sockaddr *)&tftp_addr, fromlen);
|
||||
|
||||
do
|
||||
{
|
||||
length = lwip_recvfrom(sock_fd, tftp_buffer, sizeof(tftp_buffer), 0,
|
||||
(struct sockaddr *)&from_addr, &fromlen);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
write(fd, (char*)&tftp_buffer[4], length - 4);
|
||||
rt_kprintf("#");
|
||||
|
||||
/* make ACK */
|
||||
tftp_buffer[0] = 0; tftp_buffer[1] = TFTP_ACK; /* opcode */
|
||||
/* send ACK */
|
||||
lwip_sendto(sock_fd, tftp_buffer, 4, 0,
|
||||
(struct sockaddr *)&from_addr, fromlen);
|
||||
}
|
||||
} while (length == 516);
|
||||
|
||||
if (length == 0) rt_kprintf("timeout\n");
|
||||
else rt_kprintf("done\n");
|
||||
|
||||
close(fd);
|
||||
lwip_close(sock_fd);
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(tftp_get, get file from tftp server);
|
||||
|
||||
void tftp_put(const char* host, const char* dir, const char* filename)
|
||||
{
|
||||
int fd, sock_fd, sock_opt;
|
||||
struct sockaddr_in tftp_addr, from_addr;
|
||||
rt_uint32_t length, block_number = 0;
|
||||
socklen_t fromlen;
|
||||
|
||||
/* make local file name */
|
||||
rt_snprintf((char*)tftp_buffer, sizeof(tftp_buffer),
|
||||
"%s/%s", dir, filename);
|
||||
|
||||
/* open local file for write */
|
||||
fd = open((char*)tftp_buffer, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
rt_kprintf("can't open local filename\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect to tftp server */
|
||||
inet_aton(host, (struct in_addr*)&(tftp_addr.sin_addr));
|
||||
tftp_addr.sin_family = AF_INET;
|
||||
tftp_addr.sin_port = htons(TFTP_PORT);
|
||||
|
||||
sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
||||
if (sock_fd < 0)
|
||||
{
|
||||
close(fd);
|
||||
rt_kprintf("can't create a socket\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
/* set socket option */
|
||||
sock_opt = 5000; /* 5 seconds */
|
||||
lwip_setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &sock_opt, sizeof(sock_opt));
|
||||
|
||||
/* make tftp request */
|
||||
tftp_buffer[0] = 0; /* opcode */
|
||||
tftp_buffer[1] = TFTP_WRQ; /* WRQ */
|
||||
length = rt_sprintf((char *)&tftp_buffer[2], "%s", filename) + 2;
|
||||
tftp_buffer[length] = 0; length ++;
|
||||
length += rt_sprintf((char*)&tftp_buffer[length], "%s", "octet");
|
||||
tftp_buffer[length] = 0; length ++;
|
||||
|
||||
fromlen = sizeof(struct sockaddr_in);
|
||||
|
||||
/* send request */
|
||||
lwip_sendto(sock_fd, tftp_buffer, length, 0,
|
||||
(struct sockaddr *)&tftp_addr, fromlen);
|
||||
|
||||
/* wait ACK 0 */
|
||||
length = lwip_recvfrom(sock_fd, tftp_buffer, sizeof(tftp_buffer), 0,
|
||||
(struct sockaddr *)&from_addr, &fromlen);
|
||||
if (!(tftp_buffer[0] == 0 &&
|
||||
tftp_buffer[1] == TFTP_ACK &&
|
||||
tftp_buffer[2] == 0 &&
|
||||
tftp_buffer[3] == 0))
|
||||
{
|
||||
rt_kprintf("tftp server error\n");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
block_number = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
length = read(fd, (char*)&tftp_buffer[4], 512);
|
||||
if (length > 0)
|
||||
{
|
||||
/* make opcode and block number */
|
||||
tftp_buffer[0] = 0; tftp_buffer[1] = TFTP_DATA;
|
||||
tftp_buffer[2] = (block_number >> 8) & 0xff;
|
||||
tftp_buffer[3] = block_number & 0xff;
|
||||
|
||||
lwip_sendto(sock_fd, tftp_buffer, length + 4, 0,
|
||||
(struct sockaddr *)&from_addr, fromlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("done\n");
|
||||
break; /* no data yet */
|
||||
}
|
||||
|
||||
/* receive ack */
|
||||
length = lwip_recvfrom(sock_fd, tftp_buffer, sizeof(tftp_buffer), 0,
|
||||
(struct sockaddr *)&from_addr, &fromlen);
|
||||
if (length > 0)
|
||||
{
|
||||
if ((tftp_buffer[0] == 0 &&
|
||||
tftp_buffer[1] == TFTP_ACK &&
|
||||
tftp_buffer[2] == (block_number >> 8) & 0xff) &&
|
||||
tftp_buffer[3] == (block_number & 0xff))
|
||||
{
|
||||
block_number ++;
|
||||
rt_kprintf("#");
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("server respondes with an error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (length == 0)
|
||||
{
|
||||
rt_kprintf("server timeout\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
lwip_close(sock_fd);
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(tftp_put, put file to tftp server);
|
||||
@@ -1,56 +0,0 @@
|
||||
#include <lwip/api.h>
|
||||
|
||||
#define UDP_ECHO_PORT 7
|
||||
|
||||
void udpecho_entry(void *parameter)
|
||||
{
|
||||
struct netconn *conn;
|
||||
struct netbuf *buf;
|
||||
struct ip_addr *addr;
|
||||
unsigned short port;
|
||||
|
||||
conn = netconn_new(NETCONN_UDP);
|
||||
netconn_bind(conn, IP_ADDR_ANY, 7);
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* received data to buffer */
|
||||
buf = netconn_recv(conn);
|
||||
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
|
||||
/* send the data to buffer */
|
||||
netconn_connect(conn, addr, port);
|
||||
|
||||
/* reset address, and send to client */
|
||||
buf->addr = RT_NULL;
|
||||
netconn_send(conn, buf);
|
||||
|
||||
/* release buffer */
|
||||
netbuf_delete(buf);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
static rt_thread_t echo_tid = RT_NULL;
|
||||
void udpecho(rt_uint32_t startup)
|
||||
{
|
||||
if (startup && echo_tid == RT_NULL)
|
||||
{
|
||||
echo_tid = rt_thread_create("uecho",
|
||||
udpecho_entry, RT_NULL,
|
||||
512, 30, 5);
|
||||
if (echo_tid != RT_NULL)
|
||||
rt_thread_startup(echo_tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (echo_tid != RT_NULL)
|
||||
rt_thread_delete(echo_tid); /* delete thread */
|
||||
echo_tid = RT_NULL;
|
||||
}
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(udpecho, startup or stop UDP echo server);
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
savannah.txt - How to obtain the current development source code.
|
||||
contrib.txt - How to contribute to lwIP as a developer.
|
||||
rawapi.txt - The documentation for the core API of lwIP.
|
||||
Also provides an overview about the other APIs and multithreading.
|
||||
snmp_agent.txt - The documentation for the lwIP SNMP agent.
|
||||
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
||||
@@ -1,63 +0,0 @@
|
||||
1 Introduction
|
||||
|
||||
This document describes some guidelines for people participating
|
||||
in lwIP development.
|
||||
|
||||
2 How to contribute to lwIP
|
||||
|
||||
Here is a short list of suggestions to anybody working with lwIP and
|
||||
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||
First of all as you may already know lwIP is a volunteer project so feedback
|
||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||
features of Savannah help us not lose users' input.
|
||||
|
||||
2.1 Source code style:
|
||||
|
||||
1. do not use tabs.
|
||||
2. indentation is two spaces per level (i.e. per tab).
|
||||
3. end debug messages with a trailing newline (\n).
|
||||
4. one space between keyword and opening bracket.
|
||||
5. no space between function and opening bracket.
|
||||
6. one space and no newline before opening curly braces of a block.
|
||||
7. closing curly brace on a single line.
|
||||
8. spaces surrounding assignment and comparisons.
|
||||
9. don't initialize static and/or global variables to zero, the compiler takes care of that.
|
||||
10. use current source code style as further reference.
|
||||
|
||||
2.2 Source code documentation style:
|
||||
|
||||
1. JavaDoc compliant and Doxygen compatible.
|
||||
2. Function documentation above functions in .c files, not .h files.
|
||||
(This forces you to synchronize documentation and implementation.)
|
||||
3. Use current documentation style as further reference.
|
||||
|
||||
2.3 Bug reports and patches:
|
||||
|
||||
1. Make sure you are reporting bugs or send patches against the latest
|
||||
sources. (From the latest release and/or the current CVS sources.)
|
||||
2. If you think you found a bug make sure it's not already filed in the
|
||||
bugtracker at Savannah.
|
||||
3. If you have a fix put the patch on Savannah. If it is a patch that affects
|
||||
both core and arch specific stuff please separate them so that the core can
|
||||
be applied separately while leaving the other patch 'open'. The prefered way
|
||||
is to NOT touch archs you can't test and let maintainers take care of them.
|
||||
This is a good way to see if they are used at all - the same goes for unix
|
||||
netifs except tapif.
|
||||
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
|
||||
or a patch will be enough.
|
||||
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
|
||||
5. Trivial patches (compiler warning, indentation and spelling fixes or anything obvious which takes a line or two)
|
||||
can go to the lwip-users list. This is still the fastest way of interaction and the list is not so crowded
|
||||
as to allow for loss of fixes. Putting bugs on Savannah and subsequently closing them is too much an overhead
|
||||
for reporting a compiler warning fix.
|
||||
6. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other
|
||||
trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you
|
||||
change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than
|
||||
if it's not to the point and long :) so the chances for it to be applied are greater.
|
||||
|
||||
2.4 Platform porters:
|
||||
|
||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||
can also ask for CVS access to submit and maintain your port in the contrib CVS module.
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
Raw TCP/IP interface for lwIP
|
||||
|
||||
Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
|
||||
|
||||
lwIP provides three Application Program's Interfaces (APIs) for programs
|
||||
to use for communication with the TCP/IP code:
|
||||
* low-level "core" / "callback" or "raw" API.
|
||||
* higher-level "sequential" API.
|
||||
* BSD-style socket API.
|
||||
|
||||
The sequential API provides a way for ordinary, sequential, programs
|
||||
to use the lwIP stack. It is quite similar to the BSD socket API. The
|
||||
model of execution is based on the blocking open-read-write-close
|
||||
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
||||
code and the application program must reside in different execution
|
||||
contexts (threads).
|
||||
|
||||
The socket API is a compatibility API for existing applications,
|
||||
currently it is built on top of the sequential API. It is meant to
|
||||
provide all functions needed to run socket API applications running
|
||||
on other platforms (e.g. unix / windows etc.). However, due to limitations
|
||||
in the specification of this API, there might be incompatibilities
|
||||
that require small modifications of existing programs.
|
||||
|
||||
** Threading
|
||||
|
||||
lwIP started targeting single-threaded environments. When adding multi-
|
||||
threading support, instead of making the core thread-safe, another
|
||||
approach was chosen: there is one main thread running the lwIP core
|
||||
(also known as the "tcpip_thread"). The raw API may only be used from
|
||||
this thread! Application threads using the sequential- or socket API
|
||||
communicate with this main thread through message passing.
|
||||
|
||||
As such, the list of functions that may be called from
|
||||
other threads or an ISR is very limited! Only functions
|
||||
from these API header files are thread-safe:
|
||||
- api.h
|
||||
- netbuf.h
|
||||
- netdb.h
|
||||
- netifapi.h
|
||||
- sockets.h
|
||||
- sys.h
|
||||
|
||||
Additionaly, memory (de-)allocation functions may be
|
||||
called from multiple threads (not ISR!) with NO_SYS=0
|
||||
since they are protected by SYS_LIGHTWEIGHT_PROT and/or
|
||||
semaphores.
|
||||
|
||||
Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1
|
||||
and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
|
||||
pbuf_free() may also be called from another thread or
|
||||
an ISR (since only then, mem_free - for PBUF_RAM - may
|
||||
be called from an ISR: otherwise, the HEAP is only
|
||||
protected by semaphores).
|
||||
|
||||
|
||||
** The remainder of this document discusses the "raw" API. **
|
||||
|
||||
The raw TCP/IP interface allows the application program to integrate
|
||||
better with the TCP/IP code. Program execution is event based by
|
||||
having callback functions being called from within the TCP/IP
|
||||
code. The TCP/IP code and the application program both run in the same
|
||||
thread. The sequential API has a much higher overhead and is not very
|
||||
well suited for small systems since it forces a multithreaded paradigm
|
||||
on the application.
|
||||
|
||||
The raw TCP/IP interface is not only faster in terms of code execution
|
||||
time but is also less memory intensive. The drawback is that program
|
||||
development is somewhat harder and application programs written for
|
||||
the raw TCP/IP interface are more difficult to understand. Still, this
|
||||
is the preferred way of writing applications that should be small in
|
||||
code size and memory usage.
|
||||
|
||||
Both APIs can be used simultaneously by different application
|
||||
programs. In fact, the sequential API is implemented as an application
|
||||
program using the raw TCP/IP interface.
|
||||
|
||||
--- Callbacks
|
||||
|
||||
Program execution is driven by callbacks. Each callback is an ordinary
|
||||
C function that is called from within the TCP/IP code. Every callback
|
||||
function is passed the current TCP or UDP connection state as an
|
||||
argument. Also, in order to be able to keep program specific state,
|
||||
the callback functions are called with a program specified argument
|
||||
that is independent of the TCP/IP state.
|
||||
|
||||
The function for setting the application connection state is:
|
||||
|
||||
- void tcp_arg(struct tcp_pcb *pcb, void *arg)
|
||||
|
||||
Specifies the program specific state that should be passed to all
|
||||
other callback functions. The "pcb" argument is the current TCP
|
||||
connection control block, and the "arg" argument is the argument
|
||||
that will be passed to the callbacks.
|
||||
|
||||
|
||||
--- TCP connection setup
|
||||
|
||||
The functions used for setting up connections is similar to that of
|
||||
the sequential API and of the BSD socket API. A new TCP connection
|
||||
identifier (i.e., a protocol control block - PCB) is created with the
|
||||
tcp_new() function. This PCB can then be either set to listen for new
|
||||
incoming connections or be explicitly connected to another host.
|
||||
|
||||
- struct tcp_pcb *tcp_new(void)
|
||||
|
||||
Creates a new connection identifier (PCB). If memory is not
|
||||
available for creating the new pcb, NULL is returned.
|
||||
|
||||
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Binds the pcb to a local IP address and port number. The IP address
|
||||
can be specified as IP_ADDR_ANY in order to bind the connection to
|
||||
all local IP addresses.
|
||||
|
||||
If another connection is bound to the same port, the function will
|
||||
return ERR_USE, otherwise ERR_OK is returned.
|
||||
|
||||
- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)
|
||||
|
||||
Commands a pcb to start listening for incoming connections. When an
|
||||
incoming connection is accepted, the function specified with the
|
||||
tcp_accept() function will be called. The pcb will have to be bound
|
||||
to a local port with the tcp_bind() function.
|
||||
|
||||
The tcp_listen() function returns a new connection identifier, and
|
||||
the one passed as an argument to the function will be
|
||||
deallocated. The reason for this behavior is that less memory is
|
||||
needed for a connection that is listening, so tcp_listen() will
|
||||
reclaim the memory needed for the original connection and allocate a
|
||||
new smaller memory block for the listening connection.
|
||||
|
||||
tcp_listen() may return NULL if no memory was available for the
|
||||
listening connection. If so, the memory associated with the pcb
|
||||
passed as an argument to tcp_listen() will not be deallocated.
|
||||
|
||||
- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
|
||||
Same as tcp_listen, but limits the number of outstanding connections
|
||||
in the listen queue to the value specified by the backlog argument.
|
||||
To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
|
||||
|
||||
- void tcp_accepted(struct tcp_pcb *pcb)
|
||||
|
||||
Inform lwIP that an incoming connection has been accepted. This would
|
||||
usually be called from the accept callback. This allows lwIP to perform
|
||||
housekeeping tasks, such as allowing further incoming connections to be
|
||||
queued in the listen backlog.
|
||||
|
||||
- void tcp_accept(struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
err_t err))
|
||||
|
||||
Specified the callback function that should be called when a new
|
||||
connection arrives on a listening connection.
|
||||
|
||||
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port, err_t (* connected)(void *arg,
|
||||
struct tcp_pcb *tpcb,
|
||||
err_t err));
|
||||
|
||||
Sets up the pcb to connect to the remote host and sends the
|
||||
initial SYN segment which opens the connection.
|
||||
|
||||
The tcp_connect() function returns immediately; it does not wait for
|
||||
the connection to be properly setup. Instead, it will call the
|
||||
function specified as the fourth argument (the "connected" argument)
|
||||
when the connection is established. If the connection could not be
|
||||
properly established, either because the other host refused the
|
||||
connection or because the other host didn't answer, the "err"
|
||||
callback function of this pcb (registered with tcp_err, see below)
|
||||
will be called.
|
||||
|
||||
The tcp_connect() function can return ERR_MEM if no memory is
|
||||
available for enqueueing the SYN segment. If the SYN indeed was
|
||||
enqueued successfully, the tcp_connect() function returns ERR_OK.
|
||||
|
||||
|
||||
--- Sending TCP data
|
||||
|
||||
TCP data is sent by enqueueing the data with a call to
|
||||
tcp_write(). When the data is successfully transmitted to the remote
|
||||
host, the application will be notified with a call to a specified
|
||||
callback function.
|
||||
|
||||
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t copy)
|
||||
|
||||
Enqueues the data pointed to by the argument dataptr. The length of
|
||||
the data is passed as the len parameter. The copy argument is either
|
||||
0 or 1 and indicates whether the new memory should be allocated for
|
||||
the data to be copied into. If the argument is 0, no new memory
|
||||
should be allocated and the data should only be referenced by
|
||||
pointer.
|
||||
|
||||
The tcp_write() function will fail and return ERR_MEM if the length
|
||||
of the data exceeds the current send buffer size or if the length of
|
||||
the queue of outgoing segment is larger than the upper limit defined
|
||||
in lwipopts.h. The number of bytes available in the output queue can
|
||||
be retrieved with the tcp_sndbuf() function.
|
||||
|
||||
The proper way to use this function is to call the function with at
|
||||
most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,
|
||||
the application should wait until some of the currently enqueued
|
||||
data has been successfully received by the other host and try again.
|
||||
|
||||
- void tcp_sent(struct tcp_pcb *pcb,
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t len))
|
||||
|
||||
Specifies the callback function that should be called when data has
|
||||
successfully been received (i.e., acknowledged) by the remote
|
||||
host. The len argument passed to the callback function gives the
|
||||
amount bytes that was acknowledged by the last acknowledgment.
|
||||
|
||||
|
||||
--- Receiving TCP data
|
||||
|
||||
TCP data reception is callback based - an application specified
|
||||
callback function is called when new data arrives. When the
|
||||
application has taken the data, it has to call the tcp_recved()
|
||||
function to indicate that TCP can advertise increase the receive
|
||||
window.
|
||||
|
||||
- void tcp_recv(struct tcp_pcb *pcb,
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err))
|
||||
|
||||
Sets the callback function that will be called when new data
|
||||
arrives. The callback function will be passed a NULL pbuf to
|
||||
indicate that the remote host has closed the connection. If
|
||||
there are no errors and the callback function is to return
|
||||
ERR_OK, then it must free the pbuf. Otherwise, it must not
|
||||
free the pbuf so that lwIP core code can store it.
|
||||
|
||||
- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
||||
|
||||
Must be called when the application has received the data. The len
|
||||
argument indicates the length of the received data.
|
||||
|
||||
|
||||
--- Application polling
|
||||
|
||||
When a connection is idle (i.e., no data is either transmitted or
|
||||
received), lwIP will repeatedly poll the application by calling a
|
||||
specified callback function. This can be used either as a watchdog
|
||||
timer for killing connections that have stayed idle for too long, or
|
||||
as a method of waiting for memory to become available. For instance,
|
||||
if a call to tcp_write() has failed because memory wasn't available,
|
||||
the application may use the polling functionality to call tcp_write()
|
||||
again when the connection has been idle for a while.
|
||||
|
||||
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
|
||||
|
||||
Specifies the polling interval and the callback function that should
|
||||
be called to poll the application. The interval is specified in
|
||||
number of TCP coarse grained timer shots, which typically occurs
|
||||
twice a second. An interval of 10 means that the application would
|
||||
be polled every 5 seconds.
|
||||
|
||||
|
||||
--- Closing and aborting connections
|
||||
|
||||
- err_t tcp_close(struct tcp_pcb *pcb)
|
||||
|
||||
Closes the connection. The function may return ERR_MEM if no memory
|
||||
was available for closing the connection. If so, the application
|
||||
should wait and try again either by using the acknowledgment
|
||||
callback or the polling functionality. If the close succeeds, the
|
||||
function returns ERR_OK.
|
||||
|
||||
The pcb is deallocated by the TCP code after a call to tcp_close().
|
||||
|
||||
- void tcp_abort(struct tcp_pcb *pcb)
|
||||
|
||||
Aborts the connection by sending a RST (reset) segment to the remote
|
||||
host. The pcb is deallocated. This function never fails.
|
||||
|
||||
If a connection is aborted because of an error, the application is
|
||||
alerted of this event by the err callback. Errors that might abort a
|
||||
connection are when there is a shortage of memory. The callback
|
||||
function to be called is set using the tcp_err() function.
|
||||
|
||||
- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
|
||||
err_t err))
|
||||
|
||||
The error callback function does not get the pcb passed to it as a
|
||||
parameter since the pcb may already have been deallocated.
|
||||
|
||||
|
||||
--- Lower layer TCP interface
|
||||
|
||||
TCP provides a simple interface to the lower layers of the
|
||||
system. During system initialization, the function tcp_init() has
|
||||
to be called before any other TCP function is called. When the system
|
||||
is running, the two timer functions tcp_fasttmr() and tcp_slowtmr()
|
||||
must be called with regular intervals. The tcp_fasttmr() should be
|
||||
called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and
|
||||
tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds.
|
||||
|
||||
|
||||
--- UDP interface
|
||||
|
||||
The UDP interface is similar to that of TCP, but due to the lower
|
||||
level of complexity of UDP, the interface is significantly simpler.
|
||||
|
||||
- struct udp_pcb *udp_new(void)
|
||||
|
||||
Creates a new UDP pcb which can be used for UDP communication. The
|
||||
pcb is not active until it has either been bound to a local address
|
||||
or connected to a remote address.
|
||||
|
||||
- void udp_remove(struct udp_pcb *pcb)
|
||||
|
||||
Removes and deallocates the pcb.
|
||||
|
||||
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Binds the pcb to a local address. The IP-address argument "ipaddr"
|
||||
can be IP_ADDR_ANY to indicate that it should listen to any local IP
|
||||
address. The function currently always return ERR_OK.
|
||||
|
||||
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Sets the remote end of the pcb. This function does not generate any
|
||||
network traffic, but only set the remote address of the pcb.
|
||||
|
||||
- err_t udp_disconnect(struct udp_pcb *pcb)
|
||||
|
||||
Remove the remote end of the pcb. This function does not generate
|
||||
any network traffic, but only removes the remote address of the pcb.
|
||||
|
||||
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
|
||||
Sends the pbuf p. The pbuf is not deallocated.
|
||||
|
||||
- void udp_recv(struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr,
|
||||
u16_t port),
|
||||
void *recv_arg)
|
||||
|
||||
Specifies a callback function that should be called when a UDP
|
||||
datagram is received.
|
||||
|
||||
|
||||
--- System initalization
|
||||
|
||||
A truly complete and generic sequence for initializing the lwip stack
|
||||
cannot be given because it depends on the build configuration (lwipopts.h)
|
||||
and additional initializations for your runtime environment (e.g. timers).
|
||||
|
||||
We can give you some idea on how to proceed when using the raw API.
|
||||
We assume a configuration using a single Ethernet netif and the
|
||||
UDP and TCP transport layers, IPv4 and the DHCP client.
|
||||
|
||||
Call these functions in the order of appearance:
|
||||
|
||||
- stats_init()
|
||||
|
||||
Clears the structure where runtime statistics are gathered.
|
||||
|
||||
- sys_init()
|
||||
|
||||
Not of much use since we set the NO_SYS 1 option in lwipopts.h,
|
||||
to be called for easy configuration changes.
|
||||
|
||||
- mem_init()
|
||||
|
||||
Initializes the dynamic memory heap defined by MEM_SIZE.
|
||||
|
||||
- memp_init()
|
||||
|
||||
Initializes the memory pools defined by MEMP_NUM_x.
|
||||
|
||||
- pbuf_init()
|
||||
|
||||
Initializes the pbuf memory pool defined by PBUF_POOL_SIZE.
|
||||
|
||||
- etharp_init()
|
||||
|
||||
Initializes the ARP table and queue.
|
||||
Note: you must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval
|
||||
after this initialization.
|
||||
|
||||
- ip_init()
|
||||
|
||||
Doesn't do much, it should be called to handle future changes.
|
||||
|
||||
- udp_init()
|
||||
|
||||
Clears the UDP PCB list.
|
||||
|
||||
- tcp_init()
|
||||
|
||||
Clears the TCP PCB list and clears some internal TCP timers.
|
||||
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
|
||||
predefined regular intervals after this initialization.
|
||||
|
||||
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask, struct ip_addr *gw,
|
||||
void *state, err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
|
||||
Adds your network interface to the netif_list. Allocate a struct
|
||||
netif and pass a pointer to this structure as the first argument.
|
||||
Give pointers to cleared ip_addr structures when using DHCP,
|
||||
or fill them with sane numbers otherwise. The state pointer may be NULL.
|
||||
|
||||
The init function pointer must point to a initialization function for
|
||||
your ethernet netif interface. The following code illustrates it's use.
|
||||
|
||||
err_t netif_if_init(struct netif *netif)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
for(i = 0; i < ETHARP_HWADDR_LEN; i++) netif->hwaddr[i] = some_eth_addr[i];
|
||||
init_my_eth_device();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
For ethernet drivers, the input function pointer must point to the lwip
|
||||
function ethernet_input() declared in "netif/etharp.h". Other drivers
|
||||
must use ip_input() declared in "lwip/ip.h".
|
||||
|
||||
- netif_set_default(struct netif *netif)
|
||||
|
||||
Registers the default network interface.
|
||||
|
||||
- netif_set_up(struct netif *netif)
|
||||
|
||||
When the netif is fully configured this function must be called.
|
||||
|
||||
- dhcp_start(struct netif *netif)
|
||||
|
||||
Creates a new DHCP client for this interface on the first call.
|
||||
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
|
||||
the predefined regular intervals after starting the client.
|
||||
|
||||
You can peek in the netif->dhcp struct for the actual DHCP status.
|
||||
|
||||
|
||||
--- Optimalization hints
|
||||
|
||||
The first thing you want to optimize is the lwip_standard_checksum()
|
||||
routine from src/core/inet.c. You can override this standard
|
||||
function with the #define LWIP_CHKSUM <your_checksum_routine>.
|
||||
|
||||
There are C examples given in inet.c or you might want to
|
||||
craft an assembly function for this. RFC1071 is a good
|
||||
introduction to this subject.
|
||||
|
||||
Other significant improvements can be made by supplying
|
||||
assembly or inline replacements for htons() and htonl()
|
||||
if you're using a little-endian architecture.
|
||||
#define LWIP_PLATFORM_BYTESWAP 1
|
||||
#define LWIP_PLATFORM_HTONS(x) <your_htons>
|
||||
#define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
||||
|
||||
Check your network interface driver if it reads at
|
||||
a higher speed than the maximum wire-speed. If the
|
||||
hardware isn't serviced frequently and fast enough
|
||||
buffer overflows are likely to occur.
|
||||
|
||||
E.g. when using the cs8900 driver, call cs8900if_service(ethif)
|
||||
as frequently as possible. When using an RTOS let the cs8900 interrupt
|
||||
wake a high priority task that services your driver using a binary
|
||||
semaphore or event flag. Some drivers might allow additional tuning
|
||||
to match your application and network.
|
||||
|
||||
For a production release it is recommended to set LWIP_STATS to 0.
|
||||
Note that speed performance isn't influenced much by simply setting
|
||||
high values to the memory options.
|
||||
@@ -1,135 +0,0 @@
|
||||
Daily Use Guide for using Savannah for lwIP
|
||||
|
||||
Table of Contents:
|
||||
|
||||
1 - Obtaining lwIP from the CVS repository
|
||||
2 - Committers/developers CVS access using SSH (to be written)
|
||||
3 - Merging from DEVEL branch to main trunk (stable branch)
|
||||
4 - How to release lwIP
|
||||
|
||||
|
||||
|
||||
1 Obtaining lwIP from the CVS repository
|
||||
----------------------------------------
|
||||
|
||||
To perform an anonymous CVS checkout of the main trunk (this is where
|
||||
bug fixes and incremental enhancements occur), do this:
|
||||
|
||||
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip
|
||||
|
||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||
-r STABLE-0_7 -d lwip-0.7 lwip
|
||||
|
||||
Or, obtain a specific (fixed) release as follows:
|
||||
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||
-r STABLE-0_7_0 -d lwip-0.7.0 lwip
|
||||
|
||||
3 Committers/developers CVS access using SSH
|
||||
--------------------------------------------
|
||||
|
||||
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
||||
As such, CVS commits to the server occur through a SSH tunnel for project members.
|
||||
To create a SSH2 key pair in UNIX-like environments, do this:
|
||||
|
||||
ssh-keygen -t dsa
|
||||
|
||||
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
||||
documentation and a graphic user interface. Use its key generator.
|
||||
|
||||
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
|
||||
a while so that Savannah can update its configuration (This can take minutes).
|
||||
|
||||
Try to login using SSH:
|
||||
|
||||
ssh -v your_login@cvs.sv.gnu.org
|
||||
|
||||
If it tells you:
|
||||
|
||||
Authenticating with public key "your_key_name"...
|
||||
Server refused to allocate pty
|
||||
|
||||
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
||||
are allowed to use SSH for CVS only. Now, you should be able to do this:
|
||||
|
||||
export CVS_RSH=ssh
|
||||
cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip
|
||||
|
||||
after which you can edit your local files with bug fixes or new features and
|
||||
commit them. Make sure you know what you are doing when using CVS to make
|
||||
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||
|
||||
(If SSH asks about authenticity of the host, you can check the key
|
||||
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
||||
|
||||
|
||||
3 Merging from DEVEL branch to main trunk (stable)
|
||||
--------------------------------------------------
|
||||
|
||||
Merging is a delicate process in CVS and requires the
|
||||
following disciplined steps in order to prevent conflicts
|
||||
in the future. Conflicts can be hard to solve!
|
||||
|
||||
Merging from branch A to branch B requires that the A branch
|
||||
has a tag indicating the previous merger. This tag is called
|
||||
'merged_from_A_to_B'. After merging, the tag is moved in the
|
||||
A branch to remember this merger for future merge actions.
|
||||
|
||||
IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE
|
||||
REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE
|
||||
MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME).
|
||||
|
||||
Merge all changes in DEVEL since our last merge to main:
|
||||
|
||||
In the working copy of the main trunk:
|
||||
cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL
|
||||
|
||||
(This will apply the changes between 'merged_from_DEVEL_to_main'
|
||||
and 'DEVEL' to your work set of files)
|
||||
|
||||
We can now commit the merge result.
|
||||
cvs commit -R -m "Merged from DEVEL to main."
|
||||
|
||||
If this worked out OK, we now move the tag in the DEVEL branch
|
||||
to this merge point, so we can use this point for future merges:
|
||||
|
||||
cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
|
||||
|
||||
4 How to release lwIP
|
||||
---------------------
|
||||
|
||||
First, checkout a clean copy of the branch to be released. Tag this set with
|
||||
tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example).
|
||||
|
||||
Login CVS using pserver authentication, then export a clean copy of the
|
||||
tagged tree. Export is similar to a checkout, except that the CVS metadata
|
||||
is not created locally.
|
||||
|
||||
export CVS_RSH=ssh
|
||||
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||
-r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
||||
|
||||
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
|
||||
|
||||
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
|
||||
tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3
|
||||
zip -r lwip-0.6.3.zip lwip-0.6.3
|
||||
|
||||
Now, sign the archives with a detached GPG binary signature as follows:
|
||||
|
||||
gpg -b lwip-0.6.3.tar.gz
|
||||
gpg -b lwip-0.6.3.tar.bz2
|
||||
gpg -b lwip-0.6.3.zip
|
||||
|
||||
Upload these files using anonymous FTP:
|
||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||
|
||||
ncftp>mput *0.6.3.*
|
||||
|
||||
Additionally, you may post a news item on Savannah, like this:
|
||||
|
||||
A new 0.6.3 release is now available here:
|
||||
http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3
|
||||
|
||||
You will have to submit this via the user News interface, then approve
|
||||
this via the Administrator News interface.
|
||||
@@ -1,181 +0,0 @@
|
||||
SNMPv1 agent for lwIP
|
||||
|
||||
Author: Christiaan Simons
|
||||
|
||||
This is a brief introduction how to use and configure the SNMP agent.
|
||||
Note the agent uses the raw-API UDP interface so you may also want to
|
||||
read rawapi.txt to gain a better understanding of the SNMP message handling.
|
||||
|
||||
0 Agent Capabilities
|
||||
====================
|
||||
|
||||
SNMPv1 per RFC1157
|
||||
This is an old(er) standard but is still widely supported.
|
||||
For SNMPv2c and v3 have a greater complexity and need many
|
||||
more lines of code. IMHO this breaks the idea of "lightweight IP".
|
||||
|
||||
Note the S in SNMP stands for "Simple". Note that "Simple" is
|
||||
relative. SNMP is simple compared to the complex ISO network
|
||||
management protocols CMIP (Common Management Information Protocol)
|
||||
and CMOT (CMip Over Tcp).
|
||||
|
||||
MIB II per RFC1213
|
||||
The standard lwIP stack management information base.
|
||||
This is a required MIB, so this is always enabled.
|
||||
When builing lwIP without TCP, the mib-2.tcp group is omitted.
|
||||
The groups EGP, CMOT and transmission are disabled by default.
|
||||
|
||||
Most mib-2 objects are not writable except:
|
||||
sysName, sysLocation, sysContact, snmpEnableAuthenTraps.
|
||||
Writing to or changing the ARP and IP address and route
|
||||
tables is not possible.
|
||||
|
||||
Note lwIP has a very limited notion of IP routing. It currently
|
||||
doen't have a route table and doesn't have a notion of the U,G,H flags.
|
||||
Instead lwIP uses the interface list with only one default interface
|
||||
acting as a single gateway interface (G) for the default route.
|
||||
|
||||
The agent returns a "virtual table" with the default route 0.0.0.0
|
||||
for the default interface and network routes (no H) for each
|
||||
network interface in the netif_list.
|
||||
All routes are considered to be up (U).
|
||||
|
||||
Loading additional MIBs
|
||||
MIBs can only be added in compile-time, not in run-time.
|
||||
There is no MIB compiler thus additional MIBs must be hand coded.
|
||||
|
||||
Large SNMP message support
|
||||
The packet decoding and encoding routines are designed
|
||||
to use pbuf-chains. Larger payloads then the minimum
|
||||
SNMP requirement of 484 octets are supported if the
|
||||
PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your
|
||||
local requirement.
|
||||
|
||||
1 Building the Agent
|
||||
====================
|
||||
|
||||
First of all you'll need to add the following define
|
||||
to your local lwipopts.h:
|
||||
|
||||
#define LWIP_SNMP 1
|
||||
|
||||
and add the source files in lwip/src/core/snmp
|
||||
and some snmp headers in lwip/src/include/lwip to your makefile.
|
||||
|
||||
Note you'll might need to adapt you network driver to update
|
||||
the mib2 variables for your interface.
|
||||
|
||||
2 Running the Agent
|
||||
===================
|
||||
|
||||
The following function calls must be made in your program to
|
||||
actually get the SNMP agent running.
|
||||
|
||||
Before starting the agent you should supply pointers
|
||||
to non-volatile memory for sysContact, sysLocation,
|
||||
and snmpEnableAuthenTraps. You can do this by calling
|
||||
|
||||
snmp_set_syscontact()
|
||||
snmp_set_syslocation()
|
||||
snmp_set_snmpenableauthentraps()
|
||||
|
||||
Additionally you may want to set
|
||||
|
||||
snmp_set_sysdescr()
|
||||
snmp_set_sysobjid() (if you have a private MIB)
|
||||
snmp_set_sysname()
|
||||
|
||||
Also before starting the agent you need to setup
|
||||
one or more trap destinations using these calls:
|
||||
|
||||
snmp_trap_dst_enable();
|
||||
snmp_trap_dst_ip_set();
|
||||
|
||||
In the lwIP initialisation sequence call snmp_init() just after
|
||||
the call to udp_init().
|
||||
|
||||
Exactly every 10 msec the SNMP uptime timestamp must be updated with
|
||||
snmp_inc_sysuptime(). You should call this from a timer interrupt
|
||||
or a timer signal handler depending on your runtime environment.
|
||||
|
||||
An alternative way to update the SNMP uptime timestamp is to do a call like
|
||||
snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but call to
|
||||
a lower frequency). Another one is to not call snmp_inc_sysuptime() or
|
||||
snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro.
|
||||
This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside
|
||||
snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only
|
||||
when it's queried (any function which need "sysuptime" have to call
|
||||
snmp_get_sysuptime).
|
||||
|
||||
|
||||
3 Private MIBs
|
||||
==============
|
||||
|
||||
If want to extend the agent with your own private MIB you'll need to
|
||||
add the following define to your local lwipopts.h:
|
||||
|
||||
#define SNMP_PRIVATE_MIB 1
|
||||
|
||||
You must provide the private_mib.h and associated files yourself.
|
||||
Note we don't have a "MIB compiler" that generates C source from a MIB,
|
||||
so you're required to do some serious coding if you enable this!
|
||||
|
||||
Note the lwIP enterprise ID (26381) is assigned to the lwIP project,
|
||||
ALL OBJECT IDENTIFIERS LIVING UNDER THIS ID ARE ASSIGNED BY THE lwIP
|
||||
MAINTAINERS!
|
||||
|
||||
If you need to create your own private MIB you'll need
|
||||
to apply for your own enterprise ID with IANA: http://www.iana.org/numbers.html
|
||||
|
||||
You can set it by passing a struct snmp_obj_id to the agent
|
||||
using snmp_set_sysobjid(&my_object_id), just before snmp_init().
|
||||
|
||||
Note the object identifiers for thes MIB-2 and your private MIB
|
||||
tree must be kept in sorted ascending (lexicographical) order.
|
||||
This to ensure correct getnext operation.
|
||||
|
||||
An example for a private MIB is part of the "minimal Unix" project:
|
||||
contrib/ports/unix/proj/minimal/lwip_prvmib.c
|
||||
|
||||
The next chapter gives a more detailed description of the
|
||||
MIB-2 tree and the optional private MIB.
|
||||
|
||||
4 The Gory Details
|
||||
==================
|
||||
|
||||
4.0 Object identifiers and the MIB tree.
|
||||
|
||||
We have three distinct parts for all object identifiers:
|
||||
|
||||
The prefix
|
||||
.iso.org.dod.internet
|
||||
|
||||
the middle part
|
||||
.mgmt.mib-2.ip.ipNetToMediaTable.ipNetToMediaEntry.ipNetToMediaPhysAddress
|
||||
|
||||
and the index part
|
||||
.1.192.168.0.1
|
||||
|
||||
Objects located above the .internet hierarchy aren't supported.
|
||||
Currently only the .mgmt sub-tree is available and
|
||||
when the SNMP_PRIVATE_MIB is enabled the .private tree
|
||||
becomes available too.
|
||||
|
||||
Object identifiers from incoming requests are checked
|
||||
for a matching prefix, middle part and index part
|
||||
or are expanded(*) for GetNext requests with short
|
||||
or inexisting names in the request.
|
||||
(* we call this "expansion" but this also
|
||||
resembles the "auto-completion" operation)
|
||||
|
||||
The middle part is usually located in ROM (const)
|
||||
to preserve precious RAM on small microcontrollers.
|
||||
However RAM location is possible for an dynamically
|
||||
changing private tree.
|
||||
|
||||
The index part is handled by functions which in
|
||||
turn use dynamically allocated index trees from RAM.
|
||||
These trees are updated by e.g. the etharp code
|
||||
when new entries are made or removed form the ARP cache.
|
||||
|
||||
/** @todo more gory details */
|
||||
@@ -1,228 +0,0 @@
|
||||
sys_arch interface for lwIP 0.6++
|
||||
|
||||
Author: Adam Dunkels
|
||||
|
||||
The operating system emulation layer provides a common interface
|
||||
between the lwIP code and the underlying operating system kernel. The
|
||||
general idea is that porting lwIP to new architectures requires only
|
||||
small changes to a few header files and a new sys_arch
|
||||
implementation. It is also possible to do a sys_arch implementation
|
||||
that does not rely on any underlying operating system.
|
||||
|
||||
The sys_arch provides semaphores and mailboxes to lwIP. For the full
|
||||
lwIP functionality, multiple threads support can be implemented in the
|
||||
sys_arch, but this is not required for the basic lwIP
|
||||
functionality. Previous versions of lwIP required the sys_arch to
|
||||
implement timer scheduling as well but as of lwIP 0.5 this is
|
||||
implemented in a higher layer.
|
||||
|
||||
In addition to the source file providing the functionality of sys_arch,
|
||||
the OS emulation layer must provide several header files defining
|
||||
macros used throughout lwip. The files required and the macros they
|
||||
must define are listed below the sys_arch description.
|
||||
|
||||
Semaphores can be either counting or binary - lwIP works with both
|
||||
kinds. Mailboxes are used for message passing and can be implemented
|
||||
either as a queue which allows multiple messages to be posted to a
|
||||
mailbox, or as a rendez-vous point where only one message can be
|
||||
posted at a time. lwIP works with both kinds, but the former type will
|
||||
be more efficient. A message in a mailbox is just a pointer, nothing
|
||||
more.
|
||||
|
||||
Semaphores are represented by the type "sys_sem_t" which is typedef'd
|
||||
in the sys_arch.h file. Mailboxes are equivalently represented by the
|
||||
type "sys_mbox_t". lwIP does not place any restrictions on how
|
||||
sys_sem_t or sys_mbox_t are represented internally.
|
||||
|
||||
The following functions must be implemented by the sys_arch:
|
||||
|
||||
- void sys_init(void)
|
||||
|
||||
Is called to initialize the sys_arch layer.
|
||||
|
||||
- sys_sem_t sys_sem_new(u8_t count)
|
||||
|
||||
Creates and returns a new semaphore. The "count" argument specifies
|
||||
the initial state of the semaphore.
|
||||
|
||||
- void sys_sem_free(sys_sem_t sem)
|
||||
|
||||
Deallocates a semaphore.
|
||||
|
||||
- void sys_sem_signal(sys_sem_t sem)
|
||||
|
||||
Signals a semaphore.
|
||||
|
||||
- u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
||||
|
||||
Blocks the thread while waiting for the semaphore to be
|
||||
signaled. If the "timeout" argument is non-zero, the thread should
|
||||
only be blocked for the specified time (measured in
|
||||
milliseconds). If the "timeout" argument is zero, the thread should be
|
||||
blocked until the semaphore is signalled.
|
||||
|
||||
If the timeout argument is non-zero, the return value is the number of
|
||||
milliseconds spent waiting for the semaphore to be signaled. If the
|
||||
semaphore wasn't signaled within the specified time, the return value is
|
||||
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
||||
(i.e., it was already signaled), the function may return zero.
|
||||
|
||||
Notice that lwIP implements a function with a similar name,
|
||||
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
||||
|
||||
- sys_mbox_t sys_mbox_new(int size)
|
||||
|
||||
Creates an empty mailbox for maximum "size" elements. Elements stored
|
||||
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
|
||||
in your lwipopts.h, or ignore this parameter in your implementation
|
||||
and use a default size.
|
||||
|
||||
- void sys_mbox_free(sys_mbox_t mbox)
|
||||
|
||||
Deallocates a mailbox. If there are messages still present in the
|
||||
mailbox when the mailbox is deallocated, it is an indication of a
|
||||
programming error in lwIP and the developer should be notified.
|
||||
|
||||
- void sys_mbox_post(sys_mbox_t mbox, void *msg)
|
||||
|
||||
Posts the "msg" to the mailbox. This function have to block until
|
||||
the "msg" is really posted.
|
||||
|
||||
- err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
|
||||
|
||||
Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
|
||||
is full, else, ERR_OK if the "msg" is posted.
|
||||
|
||||
- u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
||||
|
||||
Blocks the thread until a message arrives in the mailbox, but does
|
||||
not block the thread longer than "timeout" milliseconds (similar to
|
||||
the sys_arch_sem_wait() function). If "timeout" is 0, the thread should
|
||||
be blocked until a message arrives. The "msg" argument is a result
|
||||
parameter that is set by the function (i.e., by doing "*msg =
|
||||
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
||||
should be dropped.
|
||||
|
||||
The return values are the same as for the sys_arch_sem_wait() function:
|
||||
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
||||
timeout.
|
||||
|
||||
Note that a function with a similar name, sys_mbox_fetch(), is
|
||||
implemented by lwIP.
|
||||
|
||||
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
|
||||
|
||||
This is similar to sys_arch_mbox_fetch, however if a message is not
|
||||
present in the mailbox, it immediately returns with the code
|
||||
SYS_MBOX_EMPTY. On success 0 is returned.
|
||||
|
||||
To allow for efficient implementations, this can be defined as a
|
||||
function-like macro in sys_arch.h instead of a normal function. For
|
||||
example, a naive implementation could be:
|
||||
#define sys_arch_mbox_tryfetch(mbox,msg) \
|
||||
sys_arch_mbox_fetch(mbox,msg,1)
|
||||
although this would introduce unnecessary delays.
|
||||
|
||||
- struct sys_timeouts *sys_arch_timeouts(void)
|
||||
|
||||
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
|
||||
each thread has a list of timeouts which is repressented as a linked
|
||||
list of sys_timeout structures. The sys_timeouts structure holds a
|
||||
pointer to a linked list of timeouts. This function is called by
|
||||
the lwIP timeout scheduler and must not return a NULL value.
|
||||
|
||||
In a single thread sys_arch implementation, this function will
|
||||
simply return a pointer to a global sys_timeouts variable stored in
|
||||
the sys_arch module.
|
||||
|
||||
If threads are supported by the underlying operating system and if
|
||||
such functionality is needed in lwIP, the following function will have
|
||||
to be implemented as well:
|
||||
|
||||
- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
|
||||
|
||||
Starts a new thread named "name" with priority "prio" that will begin its
|
||||
execution in the function "thread()". The "arg" argument will be passed as an
|
||||
argument to the thread() function. The stack size to used for this thread is
|
||||
the "stacksize" parameter. The id of the new thread is returned. Both the id
|
||||
and the priority are system dependent.
|
||||
|
||||
- sys_prot_t sys_arch_protect(void)
|
||||
|
||||
This optional function does a "fast" critical region protection and returns
|
||||
the previous protection level. This function is only called during very short
|
||||
critical regions. An embedded system which supports ISR-based drivers might
|
||||
want to implement this function by disabling interrupts. Task-based systems
|
||||
might want to implement this by using a mutex or disabling tasking. This
|
||||
function should support recursive calls from the same task or interrupt. In
|
||||
other words, sys_arch_protect() could be called while already protected. In
|
||||
that case the return value indicates that it is already protected.
|
||||
|
||||
sys_arch_protect() is only required if your port is supporting an operating
|
||||
system.
|
||||
|
||||
- void sys_arch_unprotect(sys_prot_t pval)
|
||||
|
||||
This optional function does a "fast" set of critical region protection to the
|
||||
value specified by pval. See the documentation for sys_arch_protect() for
|
||||
more information. This function is only required if your port is supporting
|
||||
an operating system.
|
||||
|
||||
Note:
|
||||
|
||||
Be carefull with using mem_malloc() in sys_arch. When malloc() refers to
|
||||
mem_malloc() you can run into a circular function call problem. In mem.c
|
||||
mem_init() tries to allcate a semaphore using mem_malloc, which of course
|
||||
can't be performed when sys_arch uses mem_malloc.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Additional files required for the "OS support" emulation layer:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
cc.h - Architecture environment, some compiler specific, some
|
||||
environment specific (probably should move env stuff
|
||||
to sys_arch.h.)
|
||||
|
||||
Typedefs for the types used by lwip -
|
||||
u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
|
||||
|
||||
Compiler hints for packing lwip's structures -
|
||||
PACK_STRUCT_FIELD(x)
|
||||
PACK_STRUCT_STRUCT
|
||||
PACK_STRUCT_BEGIN
|
||||
PACK_STRUCT_END
|
||||
|
||||
Platform specific diagnostic output -
|
||||
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
|
||||
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
|
||||
Portability defines for printf formatters:
|
||||
U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
|
||||
|
||||
"lightweight" synchronization mechanisms -
|
||||
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
|
||||
SYS_ARCH_PROTECT(x) - enter protection mode.
|
||||
SYS_ARCH_UNPROTECT(x) - leave protection mode.
|
||||
|
||||
If the compiler does not provide memset() this file must include a
|
||||
definition of it, or include a file which defines it.
|
||||
|
||||
This file must either include a system-local <errno.h> which defines
|
||||
the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
|
||||
to make lwip/arch.h define the codes which are used throughout.
|
||||
|
||||
|
||||
perf.h - Architecture specific performance measurement.
|
||||
Measurement calls made throughout lwip, these can be defined to nothing.
|
||||
PERF_START - start measuring something.
|
||||
PERF_STOP(x) - stop measuring something, and record the result.
|
||||
|
||||
sys_arch.h - Tied to sys_arch.c
|
||||
|
||||
Arch dependent types for the following objects:
|
||||
sys_sem_t, sys_mbox_t, sys_thread_t,
|
||||
And, optionally:
|
||||
sys_prot_t
|
||||
|
||||
Defines to set vars of sys_mbox_t and sys_sem_t to NULL.
|
||||
SYS_MBOX_NULL NULL
|
||||
SYS_SEM_NULL NULL
|
||||
@@ -1,13 +0,0 @@
|
||||
api/ - The code for the high-level wrapper API. Not needed if
|
||||
you use the lowel-level call-back/raw API.
|
||||
|
||||
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||
memory and buffer management, and the low-level raw API.
|
||||
|
||||
include/ - lwIP include files.
|
||||
|
||||
netif/ - Generic network interface device drivers are kept here,
|
||||
as well as the ARP module.
|
||||
|
||||
For more information on the various subdirectories, check the FILES
|
||||
file in each directory.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Error Management module
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
static const char *err_strerr[] = {
|
||||
"Ok.", /* ERR_OK 0 */
|
||||
"Out of memory error.", /* ERR_MEM -1 */
|
||||
"Buffer error.", /* ERR_BUF -2 */
|
||||
"Timeout.", /* ERR_TIMEOUT -3 */
|
||||
"Routing problem.", /* ERR_RTE -4 */
|
||||
"Connection aborted.", /* ERR_ABRT -5 */
|
||||
"Connection reset.", /* ERR_RST -6 */
|
||||
"Connection closed.", /* ERR_CLSD -7 */
|
||||
"Not connected.", /* ERR_CONN -8 */
|
||||
"Illegal value.", /* ERR_VAL -9 */
|
||||
"Illegal argument.", /* ERR_ARG -10 */
|
||||
"Address in use.", /* ERR_USE -11 */
|
||||
"Low-level netif error.", /* ERR_IF -12 */
|
||||
"Already connected.", /* ERR_ISCONN -13 */
|
||||
"Operation in progress." /* ERR_INPROGRESS -14 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert an lwip internal error to a string representation.
|
||||
*
|
||||
* @param err an lwip internal err_t
|
||||
* @return a string representation for err
|
||||
*/
|
||||
const char *
|
||||
lwip_strerr(err_t err)
|
||||
{
|
||||
return err_strerr[-err];
|
||||
|
||||
}
|
||||
|
||||
#endif /* LWIP_DEBUG */
|
||||
@@ -1,240 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Network buffer management
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/netbuf.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Create (allocate) and initialize a new netbuf.
|
||||
* The netbuf doesn't yet contain a packet buffer!
|
||||
*
|
||||
* @return a pointer to a new netbuf
|
||||
* NULL on lack of memory
|
||||
*/
|
||||
struct
|
||||
netbuf *netbuf_new(void)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
if (buf != NULL) {
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
buf->addr = NULL;
|
||||
buf->port = 0;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
buf->toaddr = NULL;
|
||||
buf->toport = 0;
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocate a netbuf allocated by netbuf_new().
|
||||
*
|
||||
* @param buf pointer to a netbuf allocated by netbuf_new()
|
||||
*/
|
||||
void
|
||||
netbuf_delete(struct netbuf *buf)
|
||||
{
|
||||
if (buf != NULL) {
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
buf->p = buf->ptr = NULL;
|
||||
}
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate memory for a packet buffer for a given netbuf.
|
||||
*
|
||||
* @param buf the netbuf for which to allocate a packet buffer
|
||||
* @param size the size of the packet buffer to allocate
|
||||
* @return pointer to the allocated memory
|
||||
* NULL if no memory could be allocated
|
||||
*/
|
||||
void *
|
||||
netbuf_alloc(struct netbuf *buf, u16_t size)
|
||||
{
|
||||
LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
|
||||
|
||||
/* Deallocate any previously allocated memory. */
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
|
||||
if (buf->p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold size",
|
||||
(buf->p->len >= size));
|
||||
buf->ptr = buf->p;
|
||||
return buf->p->payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the packet buffer included in a netbuf
|
||||
*
|
||||
* @param buf pointer to the netbuf which contains the packet buffer to free
|
||||
*/
|
||||
void
|
||||
netbuf_free(struct netbuf *buf)
|
||||
{
|
||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = buf->ptr = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let a netbuf reference existing (non-volatile) data.
|
||||
*
|
||||
* @param buf netbuf which should reference the data
|
||||
* @param dataptr pointer to the data to reference
|
||||
* @param size size of the data
|
||||
* @return ERR_OK if data is referenced
|
||||
* ERR_MEM if data couldn't be referenced due to lack of memory
|
||||
*/
|
||||
err_t
|
||||
netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
|
||||
{
|
||||
LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||
if (buf->p == NULL) {
|
||||
buf->ptr = NULL;
|
||||
return ERR_MEM;
|
||||
}
|
||||
buf->p->payload = (void*)dataptr;
|
||||
buf->p->len = buf->p->tot_len = size;
|
||||
buf->ptr = buf->p;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain one netbuf to another (@see pbuf_chain)
|
||||
*
|
||||
* @param head the first netbuf
|
||||
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
|
||||
*/
|
||||
void
|
||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||
{
|
||||
LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;);
|
||||
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
|
||||
pbuf_cat(head->p, tail->p);
|
||||
head->ptr = head->p;
|
||||
memp_free(MEMP_NETBUF, tail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data pointer and length of the data inside a netbuf.
|
||||
*
|
||||
* @param buf netbuf to get the data from
|
||||
* @param dataptr pointer to a void pointer where to store the data pointer
|
||||
* @param len pointer to an u16_t where the length of the data is stored
|
||||
* @return ERR_OK if the information was retreived,
|
||||
* ERR_BUF on error.
|
||||
*/
|
||||
err_t
|
||||
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
||||
{
|
||||
LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
|
||||
|
||||
if (buf->ptr == NULL) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
*dataptr = buf->ptr->payload;
|
||||
*len = buf->ptr->len;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the current data pointer of a packet buffer contained in a netbuf
|
||||
* to the next part.
|
||||
* The packet buffer itself is not modified.
|
||||
*
|
||||
* @param buf the netbuf to modify
|
||||
* @return -1 if there is no next part
|
||||
* 1 if moved to the next part but now there is no next part
|
||||
* 0 if moved to the next part and there are still more parts
|
||||
*/
|
||||
s8_t
|
||||
netbuf_next(struct netbuf *buf)
|
||||
{
|
||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;);
|
||||
if (buf->ptr->next == NULL) {
|
||||
return -1;
|
||||
}
|
||||
buf->ptr = buf->ptr->next;
|
||||
if (buf->ptr->next == NULL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the current data pointer of a packet buffer contained in a netbuf
|
||||
* to the beginning of the packet.
|
||||
* The packet buffer itself is not modified.
|
||||
*
|
||||
* @param buf the netbuf to modify
|
||||
*/
|
||||
void
|
||||
netbuf_first(struct netbuf *buf)
|
||||
{
|
||||
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
|
||||
buf->ptr = buf->p;
|
||||
}
|
||||
|
||||
#endif /* LWIP_NETCONN */
|
||||
@@ -1,346 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* API functions for name resolving
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#if LWIP_DNS && LWIP_SOCKET
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
||||
struct gethostbyname_r_helper {
|
||||
struct ip_addr *addrs;
|
||||
struct ip_addr addr;
|
||||
char *aliases;
|
||||
};
|
||||
|
||||
/** h_errno is exported in netdb.h for access by applications. */
|
||||
#if LWIP_DNS_API_DECLARE_H_ERRNO
|
||||
int h_errno;
|
||||
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
|
||||
|
||||
/** define "hostent" variables storage: 0 if we use a static (but unprotected)
|
||||
* set of variables for lwip_gethostbyname, 1 if we use a local storage */
|
||||
#ifndef LWIP_DNS_API_HOSTENT_STORAGE
|
||||
#define LWIP_DNS_API_HOSTENT_STORAGE 0
|
||||
#endif
|
||||
|
||||
/** define "hostent" variables storage */
|
||||
#if LWIP_DNS_API_HOSTENT_STORAGE
|
||||
#define HOSTENT_STORAGE
|
||||
#else
|
||||
#define HOSTENT_STORAGE static
|
||||
#endif /* LWIP_DNS_API_STATIC_HOSTENT */
|
||||
|
||||
/**
|
||||
* Returns an entry containing addresses of address family AF_INET
|
||||
* for the host with name name.
|
||||
* Due to dns_gethostbyname limitations, only one address is returned.
|
||||
*
|
||||
* @param name the hostname to resolve
|
||||
* @return an entry containing addresses of address family AF_INET
|
||||
* for the host with name name
|
||||
*/
|
||||
struct hostent*
|
||||
lwip_gethostbyname(const char *name)
|
||||
{
|
||||
err_t err;
|
||||
struct ip_addr addr;
|
||||
|
||||
/* buffer variables for lwip_gethostbyname() */
|
||||
HOSTENT_STORAGE struct hostent s_hostent;
|
||||
HOSTENT_STORAGE char *s_aliases;
|
||||
HOSTENT_STORAGE struct ip_addr s_hostent_addr;
|
||||
HOSTENT_STORAGE struct ip_addr *s_phostent_addr;
|
||||
|
||||
/* query host IP address */
|
||||
err = netconn_gethostbyname(name, &addr);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill hostent */
|
||||
s_hostent_addr = addr;
|
||||
s_phostent_addr = &s_hostent_addr;
|
||||
s_hostent.h_name = (char*)name;
|
||||
s_hostent.h_aliases = &s_aliases;
|
||||
s_hostent.h_addrtype = AF_INET;
|
||||
s_hostent.h_length = sizeof(struct ip_addr);
|
||||
s_hostent.h_addr_list = (char**)&s_phostent_addr;
|
||||
|
||||
#if DNS_DEBUG
|
||||
/* dump hostent */
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases));
|
||||
if (s_hostent.h_aliases != NULL) {
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_aliases[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list));
|
||||
if (s_hostent.h_addr_list != NULL) {
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa(s_hostent.h_addr_list[idx])));
|
||||
}
|
||||
}
|
||||
#endif /* DNS_DEBUG */
|
||||
|
||||
#if LWIP_DNS_API_HOSTENT_STORAGE
|
||||
/* this function should return the "per-thread" hostent after copy from s_hostent */
|
||||
return sys_thread_hostent(&s_hostent);
|
||||
#else
|
||||
return &s_hostent;
|
||||
#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread-safe variant of lwip_gethostbyname: instead of using a static
|
||||
* buffer, this function takes buffer and errno pointers as arguments
|
||||
* and uses these for the result.
|
||||
*
|
||||
* @param name the hostname to resolve
|
||||
* @param ret pre-allocated struct where to store the result
|
||||
* @param buf pre-allocated buffer where to store additional data
|
||||
* @param buflen the size of buf
|
||||
* @param result pointer to a hostent pointer that is set to ret on success
|
||||
* and set to zero on error
|
||||
* @param h_errnop pointer to an int where to store errors (instead of modifying
|
||||
* the global h_errno)
|
||||
* @return 0 on success, non-zero on error, additional error information
|
||||
* is stored in *h_errnop instead of h_errno to be thread-safe
|
||||
*/
|
||||
int
|
||||
lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
size_t buflen, struct hostent **result, int *h_errnop)
|
||||
{
|
||||
err_t err;
|
||||
struct gethostbyname_r_helper *h;
|
||||
char *hostname;
|
||||
size_t namelen;
|
||||
int lh_errno;
|
||||
|
||||
if (h_errnop == NULL) {
|
||||
/* ensure h_errnop is never NULL */
|
||||
h_errnop = &lh_errno;
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
/* not all arguments given */
|
||||
*h_errnop = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
/* first thing to do: set *result to nothing */
|
||||
*result = NULL;
|
||||
if ((name == NULL) || (ret == NULL) || (buf == 0)) {
|
||||
/* not all arguments given */
|
||||
*h_errnop = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
namelen = strlen(name);
|
||||
if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
|
||||
/* buf can't hold the data needed + a copy of name */
|
||||
*h_errnop = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
|
||||
hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
|
||||
|
||||
/* query host IP address */
|
||||
err = netconn_gethostbyname(name, &(h->addr));
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
||||
*h_errnop = ENSRNOTFOUND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* copy the hostname into buf */
|
||||
MEMCPY(hostname, name, namelen);
|
||||
hostname[namelen] = 0;
|
||||
|
||||
/* fill hostent */
|
||||
h->addrs = &(h->addr);
|
||||
h->aliases = NULL;
|
||||
ret->h_name = (char*)hostname;
|
||||
ret->h_aliases = &(h->aliases);
|
||||
ret->h_addrtype = AF_INET;
|
||||
ret->h_length = sizeof(struct ip_addr);
|
||||
ret->h_addr_list = (char**)&(h->addrs);
|
||||
|
||||
/* set result != NULL */
|
||||
*result = ret;
|
||||
|
||||
/* return success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees one or more addrinfo structures returned by getaddrinfo(), along with
|
||||
* any additional storage associated with those structures. If the ai_next field
|
||||
* of the structure is not null, the entire list of structures is freed.
|
||||
*
|
||||
* @param ai struct addrinfo to free
|
||||
*/
|
||||
void
|
||||
lwip_freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *next;
|
||||
|
||||
while (ai != NULL) {
|
||||
next = ai->ai_next;
|
||||
mem_free(ai);
|
||||
ai = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the name of a service location (for example, a host name) and/or
|
||||
* a service name and returns a set of socket addresses and associated
|
||||
* information to be used in creating a socket with which to address the
|
||||
* specified service.
|
||||
* Memory for the result is allocated internally and must be freed by calling
|
||||
* lwip_freeaddrinfo()!
|
||||
*
|
||||
* Due to a limitation in dns_gethostbyname, only the first address of a
|
||||
* host is returned.
|
||||
* Also, service names are not supported (only port numbers)!
|
||||
*
|
||||
* @param nodename descriptive name or address string of the host
|
||||
* (may be NULL -> local address)
|
||||
* @param servname port number as string of NULL
|
||||
* @param hints structure containing input values that set socktype and protocol
|
||||
* @param res pointer to a pointer where to store the result (set to NULL on failure)
|
||||
* @return 0 on success, non-zero on failure
|
||||
*/
|
||||
int
|
||||
lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
err_t err;
|
||||
struct ip_addr addr;
|
||||
struct addrinfo *ai;
|
||||
struct sockaddr_in *sa = NULL;
|
||||
int port_nr = 0;
|
||||
size_t total_size;
|
||||
size_t namelen = 0;
|
||||
|
||||
if (res == NULL) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
*res = NULL;
|
||||
if ((nodename == NULL) && (servname == NULL)) {
|
||||
return EAI_NONAME;
|
||||
}
|
||||
|
||||
if (servname != NULL) {
|
||||
/* service name specified: convert to port number
|
||||
* @todo?: currently, only ASCII integers (port numbers) are supported! */
|
||||
port_nr = atoi(servname);
|
||||
if ((port_nr <= 0) || (port_nr > 0xffff)) {
|
||||
return EAI_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
if (nodename != NULL) {
|
||||
/* service location specified, try to resolve */
|
||||
err = netconn_gethostbyname(nodename, &addr);
|
||||
if (err != ERR_OK) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
} else {
|
||||
/* service location specified, use loopback address */
|
||||
addr.addr = htonl(INADDR_LOOPBACK);
|
||||
}
|
||||
|
||||
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in);
|
||||
if (nodename != NULL) {
|
||||
namelen = strlen(nodename);
|
||||
LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
|
||||
total_size += namelen + 1;
|
||||
}
|
||||
ai = mem_malloc(total_size);
|
||||
if (ai == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
memset(ai, 0, total_size);
|
||||
sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo));
|
||||
/* set up sockaddr */
|
||||
sa->sin_addr.s_addr = addr.addr;
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_len = sizeof(struct sockaddr_in);
|
||||
sa->sin_port = htons(port_nr);
|
||||
|
||||
/* set up addrinfo */
|
||||
ai->ai_family = AF_INET;
|
||||
if (hints != NULL) {
|
||||
/* copy socktype & protocol from hints if specified */
|
||||
ai->ai_socktype = hints->ai_socktype;
|
||||
ai->ai_protocol = hints->ai_protocol;
|
||||
}
|
||||
if (nodename != NULL) {
|
||||
/* copy nodename to canonname if specified */
|
||||
ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
||||
MEMCPY(ai->ai_canonname, nodename, namelen);
|
||||
ai->ai_canonname[namelen] = 0;
|
||||
}
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
ai->ai_addr = (struct sockaddr*)sa;
|
||||
|
||||
*res = ai;
|
||||
|
||||
return 0;
|
||||
memerr:
|
||||
if (ai != NULL) {
|
||||
mem_free(ai);
|
||||
}
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
||||
@@ -1,162 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Network Interface Sequential API module
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/netifapi.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
/**
|
||||
* Call netif_add() inside the tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_add( struct netifapi_msg_msg *msg)
|
||||
{
|
||||
if (!netif_add( msg->netif,
|
||||
msg->msg.add.ipaddr,
|
||||
msg->msg.add.netmask,
|
||||
msg->msg.add.gw,
|
||||
msg->msg.add.state,
|
||||
msg->msg.add.init,
|
||||
msg->msg.add.input)) {
|
||||
msg->err = ERR_IF;
|
||||
} else {
|
||||
msg->err = ERR_OK;
|
||||
}
|
||||
TCPIP_NETIFAPI_ACK(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call netif_set_addr() inside the tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
|
||||
{
|
||||
netif_set_addr( msg->netif,
|
||||
msg->msg.add.ipaddr,
|
||||
msg->msg.add.netmask,
|
||||
msg->msg.add.gw);
|
||||
msg->err = ERR_OK;
|
||||
TCPIP_NETIFAPI_ACK(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
|
||||
* tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_common( struct netifapi_msg_msg *msg)
|
||||
{
|
||||
if (msg->msg.common.errtfunc!=NULL) {
|
||||
msg->err =
|
||||
msg->msg.common.errtfunc(msg->netif);
|
||||
} else {
|
||||
msg->err = ERR_OK;
|
||||
msg->msg.common.voidfunc(msg->netif);
|
||||
}
|
||||
TCPIP_NETIFAPI_ACK(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call netif_add() in a thread-safe way by running that function inside the
|
||||
* tcpip_thread context.
|
||||
*
|
||||
* @note for params @see netif_add()
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_add(struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_add;
|
||||
msg.msg.netif = netif;
|
||||
msg.msg.msg.add.ipaddr = ipaddr;
|
||||
msg.msg.msg.add.netmask = netmask;
|
||||
msg.msg.msg.add.gw = gw;
|
||||
msg.msg.msg.add.state = state;
|
||||
msg.msg.msg.add.init = init;
|
||||
msg.msg.msg.add.input = input;
|
||||
TCPIP_NETIFAPI(&msg);
|
||||
return msg.msg.err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call netif_set_addr() in a thread-safe way by running that function inside the
|
||||
* tcpip_thread context.
|
||||
*
|
||||
* @note for params @see netif_set_addr()
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_set_addr(struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw)
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_set_addr;
|
||||
msg.msg.netif = netif;
|
||||
msg.msg.msg.add.ipaddr = ipaddr;
|
||||
msg.msg.msg.add.netmask = netmask;
|
||||
msg.msg.msg.add.gw = gw;
|
||||
TCPIP_NETIFAPI(&msg);
|
||||
return msg.msg.err;
|
||||
}
|
||||
|
||||
/**
|
||||
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
|
||||
* way by running that function inside the tcpip_thread context.
|
||||
*
|
||||
* @note use only for functions where there is only "netif" parameter.
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_common( struct netif *netif,
|
||||
void (* voidfunc)(struct netif *netif),
|
||||
err_t (* errtfunc)(struct netif *netif) )
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_common;
|
||||
msg.msg.netif = netif;
|
||||
msg.msg.msg.common.voidfunc = voidfunc;
|
||||
msg.msg.msg.common.errtfunc = errtfunc;
|
||||
TCPIP_NETIFAPI(&msg);
|
||||
return msg.msg.err;
|
||||
}
|
||||
|
||||
#endif /* LWIP_NETIF_API */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: cc.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $
|
||||
*/
|
||||
#ifndef __ARCH_CC_H__
|
||||
#define __ARCH_CC_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
typedef rt_uint8_t u8_t;
|
||||
typedef rt_int8_t s8_t;
|
||||
typedef rt_uint16_t u16_t;
|
||||
typedef rt_int16_t s16_t;
|
||||
typedef rt_uint32_t u32_t;
|
||||
typedef rt_int32_t s32_t;
|
||||
typedef rt_uint32_t mem_ptr_t;
|
||||
|
||||
#define U16_F "hu"
|
||||
#define S16_F "hd"
|
||||
#define X16_F "hx"
|
||||
#define U32_F "lu"
|
||||
#define S32_F "ld"
|
||||
#define X32_F "lx"
|
||||
|
||||
#ifdef RT_USING_NEWLIB
|
||||
#include <errno.h>
|
||||
/* some errno not defined in newlib */
|
||||
#define ENSRNOTFOUND 163 /* Domain name not found */
|
||||
/* WARNING: ESHUTDOWN also not defined in newlib. We chose
|
||||
180 here because the number "108" which is used
|
||||
in arch.h has been assigned to another error code. */
|
||||
#define ESHUTDOWN 180
|
||||
#else
|
||||
#define LWIP_PROVIDE_ERRNO
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_MINILIBC
|
||||
#include <time.h>
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#endif
|
||||
|
||||
#if defined(__CC_ARM) /* ARMCC compiler */
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_END
|
||||
#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#define PACK_STRUCT_USE_INCLUDES
|
||||
#elif defined(__GNUC__) /* GNU GCC Compiler */
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#define PACK_STRUCT_STRUCT __attribute__((packed))
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_END
|
||||
#endif
|
||||
|
||||
void sys_arch_assert(const char* file, int line);
|
||||
#ifdef LWIP_DEBUG
|
||||
#define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0)
|
||||
#define LWIP_PLATFORM_ASSERT(x) { rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__); }
|
||||
#else
|
||||
#define LWIP_PLATFORM_DIAG(x)
|
||||
#define LWIP_PLATFORM_ASSERT(x)
|
||||
#endif
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#endif /* __ARCH_CC_H__ */
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: cpu.h,v 1.1.1.1 2004/12/16 14:17:14 bear Exp $
|
||||
*/
|
||||
#ifndef __ARCH_CPU_H__
|
||||
#define __ARCH_CPU_H__
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif /* BYTE_ORDER */
|
||||
|
||||
#endif /* __ARCH_CPU_H__ */
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#pragma pack()
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: init.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $
|
||||
*/
|
||||
#ifndef __ARCH_INIT_H__
|
||||
#define __ARCH_INIT_H__
|
||||
|
||||
#define TCPIP_INIT_DONE(arg) sys_sem_signal(*(sys_sem_t *)arg)
|
||||
|
||||
#endif /* __ARCH_INIT_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: lib.h,v 1.1.1.1 2004/12/16 14:17:14 bear Exp $
|
||||
*/
|
||||
#ifndef __ARCH_LIB_H__
|
||||
#define __ARCH_LIB_H__
|
||||
|
||||
#define bcopy(s, d, l) rt_memcpy(s, d, l)
|
||||
#define bzero(d, n) rt_memset(d, 0, n)
|
||||
|
||||
#endif /* __ARCH_LIB_H__ */
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: perf.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $
|
||||
*/
|
||||
#ifndef __ARCH_PERF_H__
|
||||
#define __ARCH_PERF_H__
|
||||
|
||||
//#include <sys/times.h>
|
||||
|
||||
#define PERF_START /* null definition */
|
||||
#define PERF_STOP(x) /* null definition */
|
||||
|
||||
/*
|
||||
void perf_print(unsigned long c1l, unsigned long c1h,
|
||||
unsigned long c2l, unsigned long c2h,
|
||||
char *key);
|
||||
|
||||
void perf_print_times(struct tms *start, struct tms *end, char *key);
|
||||
|
||||
void perf_init(char *fname);
|
||||
*/
|
||||
#endif /* __ARCH_PERF_H__ */
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: sys_arch.h,v 1.3 2005/03/13 16:03:23 bear Exp $
|
||||
*/
|
||||
#ifndef __ARCH_SYS_ARCH_H__
|
||||
#define __ARCH_SYS_ARCH_H__
|
||||
|
||||
#include "arch/cpu.h"
|
||||
#include "arch/cc.h"
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#define SYS_MBOX_NULL RT_NULL
|
||||
#define SYS_SEM_NULL RT_NULL
|
||||
|
||||
typedef u32_t sys_prot_t;
|
||||
|
||||
#define SYS_MBOX_SIZE 10
|
||||
#define SYS_LWIP_TIMER_NAME "timer"
|
||||
#define SYS_LWIP_MBOX_NAME "mbox"
|
||||
#define SYS_LWIP_SEM_NAME "sem"
|
||||
|
||||
typedef rt_sem_t sys_sem_t;
|
||||
typedef rt_mailbox_t sys_mbox_t;
|
||||
typedef rt_thread_t sys_thread_t;
|
||||
|
||||
#endif /* __ARCH_SYS_ARCH_H__ */
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef __LWIP_SYS_INIT_H__
|
||||
#define __LWIP_SYS_INIT_H__
|
||||
|
||||
void lwip_sys_init(void);
|
||||
void lwip_system_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "arch/sys_arch.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define LWIP_THREAD_MAGIC 0x1919
|
||||
#define LWIP_THREAD_NAME (rt_thread_self()->name)
|
||||
struct lwip_thread
|
||||
{
|
||||
rt_uint32_t magic;
|
||||
struct sys_timeouts timeouts;
|
||||
|
||||
rt_thread_t tid;
|
||||
};
|
||||
|
||||
void sys_init(void)
|
||||
{
|
||||
/* nothing to do in RT-Thread */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sys_sem_t sys_sem_new(u8_t count)
|
||||
{
|
||||
static unsigned short counter = 0;
|
||||
char tname[RT_NAME_MAX];
|
||||
|
||||
rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Create sem: %s \n", LWIP_THREAD_NAME, tname));
|
||||
|
||||
counter++;
|
||||
|
||||
return rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);
|
||||
}
|
||||
|
||||
void sys_sem_free(sys_sem_t sem)
|
||||
{
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Delete sem: %s \n", LWIP_THREAD_NAME,
|
||||
sem->parent.parent.name));
|
||||
|
||||
rt_sem_delete(sem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void sys_sem_signal(sys_sem_t sem)
|
||||
{
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Release signal: %s , %d\n", LWIP_THREAD_NAME,
|
||||
sem->parent.parent.name, sem->value));
|
||||
|
||||
rt_sem_release(sem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
||||
{
|
||||
rt_err_t ret;
|
||||
s32_t t;
|
||||
u32_t tick;
|
||||
|
||||
/* get the begin tick */
|
||||
tick = rt_tick_get();
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Wait sem: %s , %d\n", LWIP_THREAD_NAME,
|
||||
sem->parent.parent.name, sem->value));
|
||||
|
||||
if(timeout == 0)
|
||||
t = RT_WAITING_FOREVER;
|
||||
else
|
||||
{
|
||||
/* convirt msecond to os tick */
|
||||
if (timeout < (1000/RT_TICK_PER_SECOND)) t = 1;
|
||||
else t = timeout / (1000/RT_TICK_PER_SECOND);
|
||||
}
|
||||
|
||||
ret = rt_sem_take(sem, t);
|
||||
|
||||
if (ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT;
|
||||
else if (ret == RT_EOK) ret = 1;
|
||||
|
||||
/* get elapse msecond */
|
||||
tick = rt_tick_get() - tick;
|
||||
|
||||
/* convert tick to msecond */
|
||||
tick = tick * (1000/RT_TICK_PER_SECOND);
|
||||
if (tick == 0) tick = 1;
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
sys_mbox_t sys_mbox_new(int size)
|
||||
{
|
||||
static unsigned short counter = 0;
|
||||
char tname[RT_NAME_MAX];
|
||||
|
||||
rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter);
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Create mbox: %s \n", LWIP_THREAD_NAME, tname));
|
||||
|
||||
counter++;
|
||||
|
||||
return rt_mb_create(tname, size, RT_IPC_FLAG_FIFO);
|
||||
}
|
||||
|
||||
void sys_mbox_free(sys_mbox_t mbox)
|
||||
{
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Delete mbox: %s\n", LWIP_THREAD_NAME,
|
||||
mbox->mb->parent.parent.name));
|
||||
|
||||
rt_mb_delete(mbox);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void sys_mbox_post(sys_mbox_t mbox, void *msg)
|
||||
{
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Post mail: %s ,0x%x\n", LWIP_THREAD_NAME,
|
||||
mbox->mb->parent.parent.name, (rt_uint32_t)msg));
|
||||
|
||||
rt_mb_send_wait(mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
|
||||
{
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Try post mail: %s ,0x%x\n", LWIP_THREAD_NAME,
|
||||
mbox->mb->parent.parent.name, (rt_uint32_t)msg));
|
||||
|
||||
if (rt_mb_send(mbox, (rt_uint32_t)msg) == RT_EOK) return ERR_OK;
|
||||
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
||||
{
|
||||
rt_err_t ret;
|
||||
s32_t t;
|
||||
u32_t tick;
|
||||
|
||||
/* get the begin tick */
|
||||
tick = rt_tick_get();
|
||||
|
||||
if(timeout == 0)
|
||||
t = RT_WAITING_FOREVER;
|
||||
else
|
||||
{
|
||||
/* convirt msecond to os tick */
|
||||
if (timeout < (1000/RT_TICK_PER_SECOND)) t = 1;
|
||||
else t = timeout / (1000/RT_TICK_PER_SECOND);
|
||||
}
|
||||
|
||||
ret = rt_mb_recv(mbox, (rt_uint32_t *)msg, t);
|
||||
|
||||
if(ret == -RT_ETIMEOUT)
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
else
|
||||
{
|
||||
LWIP_ASSERT("rt_mb_recv returned with error!", ret == RT_EOK);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Fetch mail: %s , 0x%x\n", LWIP_THREAD_NAME,
|
||||
mbox->mb->parent.parent.name, *(rt_uint32_t **)msg));
|
||||
|
||||
/* get elapse msecond */
|
||||
tick = rt_tick_get() - tick;
|
||||
|
||||
/* convert tick to msecond */
|
||||
tick = tick * (1000/RT_TICK_PER_SECOND);
|
||||
if (tick == 0) tick = 1;
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rt_mb_recv(mbox, (rt_uint32_t *)msg, 0);
|
||||
|
||||
if(ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT;
|
||||
else if (ret == RT_EOK) ret = 1;
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("%s, Fetch mail: %s , 0x%x\n", LWIP_THREAD_NAME,
|
||||
mbox->mb->parent.parent.name, *(rt_uint32_t **)msg));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct sys_timeouts *sys_arch_timeouts(void)
|
||||
{
|
||||
rt_thread_t self = rt_thread_self();
|
||||
struct lwip_thread* lwip_th = (struct lwip_thread*)self->user_data;
|
||||
|
||||
if ((lwip_th != RT_NULL) && (lwip_th->magic == LWIP_THREAD_MAGIC))
|
||||
return &(lwip_th->timeouts);
|
||||
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
|
||||
{
|
||||
rt_thread_t t;
|
||||
struct lwip_thread* lwip_th;
|
||||
|
||||
/* create lwip thread */
|
||||
lwip_th = (struct lwip_thread*) rt_malloc (sizeof(struct lwip_thread));
|
||||
RT_ASSERT(lwip_th != RT_NULL);
|
||||
|
||||
/* create thread */
|
||||
t = rt_thread_create(name, thread, arg, stacksize, prio, 20);
|
||||
RT_ASSERT(t != RT_NULL);
|
||||
t->user_data = (rt_uint32_t)lwip_th;
|
||||
|
||||
/* init lwip_thread */
|
||||
lwip_th->magic = LWIP_THREAD_MAGIC;
|
||||
lwip_th->timeouts.next = RT_NULL;
|
||||
lwip_th->tid = t;
|
||||
|
||||
/* startup thread */
|
||||
rt_thread_startup(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
sys_prot_t sys_arch_protect(void)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
/* must also lock scheduler */
|
||||
rt_enter_critical();
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
void sys_arch_unprotect(sys_prot_t pval)
|
||||
{
|
||||
/* unlock scheduler */
|
||||
rt_exit_critical();
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(pval);
|
||||
|
||||
return;
|
||||
}
|
||||
void sys_arch_assert(const char* file, int line)
|
||||
{
|
||||
rt_kprintf("\nAssertion: %d in %s, thread %s\n", line, file,
|
||||
rt_thread_self()->name);
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/dhcp.h"
|
||||
|
||||
#include "netif/ethernetif.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
static err_t netif_device_init(struct netif *netif)
|
||||
{
|
||||
struct eth_device *ethif;
|
||||
|
||||
ethif = (struct eth_device*)netif->state;
|
||||
if (ethif != RT_NULL)
|
||||
{
|
||||
rt_device_t device;
|
||||
|
||||
/* get device object */
|
||||
device = (rt_device_t) ethif;
|
||||
if (rt_device_init(device) != RT_EOK)
|
||||
{
|
||||
return ERR_IF;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
static void tcpip_init_done_callback(void *arg)
|
||||
{
|
||||
rt_device_t device;
|
||||
struct eth_device *ethif;
|
||||
struct ip_addr ipaddr, netmask, gw;
|
||||
struct rt_list_node* node;
|
||||
struct rt_object* object;
|
||||
struct rt_object_information *information;
|
||||
|
||||
LWIP_ASSERT("invalid arg.\n",arg);
|
||||
|
||||
IP4_ADDR(&gw, 0,0,0,0);
|
||||
IP4_ADDR(&ipaddr, 0,0,0,0);
|
||||
IP4_ADDR(&netmask, 0,0,0,0);
|
||||
|
||||
/* enter critical */
|
||||
rt_enter_critical();
|
||||
|
||||
/* for each network interfaces */
|
||||
information = rt_object_get_information(RT_Object_Class_Device);
|
||||
RT_ASSERT(information != RT_NULL);
|
||||
|
||||
for (node = information->object_list.next; node != &(information->object_list); node = node->next)
|
||||
{
|
||||
object = rt_list_entry(node, struct rt_object, list);
|
||||
device = (rt_device_t) object;
|
||||
if (device->type == RT_Device_Class_NetIf)
|
||||
{
|
||||
ethif = (struct eth_device*)device;
|
||||
|
||||
/* leave critical */
|
||||
rt_exit_critical();
|
||||
|
||||
netif_add(ethif->netif, &ipaddr, &netmask, &gw,
|
||||
ethif, netif_device_init, tcpip_input);
|
||||
|
||||
if (netif_default == RT_NULL)
|
||||
netif_set_default(ethif->netif);
|
||||
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(ethif->netif);
|
||||
#else
|
||||
netif_set_up(ethif->netif);
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_NETIF_LINK_CALLBACK
|
||||
netif_set_link_up(ethif->netif);
|
||||
#endif
|
||||
|
||||
/* enter critical */
|
||||
rt_enter_critical();
|
||||
}
|
||||
}
|
||||
|
||||
/* leave critical */
|
||||
rt_exit_critical();
|
||||
|
||||
rt_sem_release((rt_sem_t)arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* LwIP system initialization
|
||||
*/
|
||||
void lwip_system_init(void)
|
||||
{
|
||||
rt_err_t rc;
|
||||
struct rt_semaphore done_sem;
|
||||
|
||||
rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO);
|
||||
|
||||
if(rc != RT_EOK)
|
||||
{
|
||||
LWIP_ASSERT("Failed to create semaphore", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
tcpip_init(tcpip_init_done_callback,(void *)&done_sem);
|
||||
|
||||
/* waiting for initialization done */
|
||||
if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK)
|
||||
{
|
||||
rt_sem_detach(&done_sem);
|
||||
return;
|
||||
}
|
||||
rt_sem_detach(&done_sem);
|
||||
|
||||
/* set default ip address */
|
||||
#if !LWIP_DHCP
|
||||
{
|
||||
struct ip_addr ipaddr, netmask, gw;
|
||||
|
||||
ipaddr.addr = inet_addr(RT_LWIP_IPADDR);
|
||||
gw.addr = inet_addr(RT_LWIP_GWADDR);
|
||||
netmask.addr = inet_addr(RT_LWIP_MSKADDR);
|
||||
|
||||
netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatible with RT-Thread 0.2.x/0.3.x
|
||||
*/
|
||||
void lwip_sys_init(void)
|
||||
{
|
||||
lwip_system_init();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,274 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Modules initialization
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/snmp_msg.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
/* Compile-time sanity checks for configuration errors.
|
||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||
*/
|
||||
#ifndef BYTE_ORDER
|
||||
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
|
||||
#endif
|
||||
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
|
||||
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_ARP && ARP_QUEUEING)
|
||||
#error "If you want to use ARP Queueing, you have to define LWIP_ARP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_UDPLITE)
|
||||
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_SNMP)
|
||||
#error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_DHCP)
|
||||
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_IGMP)
|
||||
#error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_DNS)
|
||||
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
|
||||
#error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
|
||||
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
|
||||
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
|
||||
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
|
||||
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && (TCP_WND > 0xffff))
|
||||
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
||||
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
||||
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))
|
||||
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
|
||||
#endif
|
||||
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
|
||||
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (PPP_SUPPORT && (NO_SYS==1))
|
||||
#error "If you want to use PPP, you have to define NO_SYS=0 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_NETIF_API && (NO_SYS==1))
|
||||
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||
#endif
|
||||
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
|
||||
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||
#endif
|
||||
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
|
||||
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_NETCONN && LWIP_SOCKET)
|
||||
#error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
|
||||
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
|
||||
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_ARP && LWIP_AUTOIP)
|
||||
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0))
|
||||
#error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0))
|
||||
#error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
|
||||
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
|
||||
#endif
|
||||
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
|
||||
#if ((NO_SYS==0) && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)))
|
||||
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
|
||||
#endif
|
||||
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
|
||||
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
|
||||
#endif
|
||||
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
|
||||
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
|
||||
#endif
|
||||
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
|
||||
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
|
||||
#endif
|
||||
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
|
||||
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
|
||||
#endif
|
||||
#if (TCP_QUEUE_OOSEQ && !LWIP_TCP)
|
||||
#error "TCP_QUEUE_OOSEQ requires LWIP_TCP"
|
||||
#endif
|
||||
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
||||
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
||||
#endif
|
||||
#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT
|
||||
#error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on"
|
||||
#endif
|
||||
|
||||
|
||||
/* Compile-time checks for deprecated options.
|
||||
*/
|
||||
#ifdef MEMP_NUM_TCPIP_MSG
|
||||
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#ifdef MEMP_NUM_API_MSG
|
||||
#error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#ifdef TCP_REXMIT_DEBUG
|
||||
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#ifdef RAW_STATS
|
||||
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#ifdef ETHARP_QUEUE_FIRST
|
||||
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#ifdef ETHARP_ALWAYS_INSERT
|
||||
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#if SO_REUSE
|
||||
/* I removed the lot since this was an ugly hack. It broke the raw-API.
|
||||
It also came with many ugly goto's, Christiaan Simons. */
|
||||
#error "SO_REUSE currently unavailable, this was a hack"
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
static void
|
||||
lwip_sanity_check(void)
|
||||
{
|
||||
/* Warnings */
|
||||
#if LWIP_NETCONN
|
||||
if (MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN\n"));
|
||||
#endif /* LWIP_NETCONN */
|
||||
#if LWIP_TCP
|
||||
if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN\n"));
|
||||
if (TCP_SND_BUF < 2 * TCP_MSS)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n"));
|
||||
if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS)))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n"));
|
||||
if (TCP_SNDLOWAT > TCP_SND_BUF)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n"));
|
||||
if (TCP_WND > (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n"));
|
||||
if (TCP_WND < TCP_MSS)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n"));
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
#else /* LWIP_DEBUG */
|
||||
#define lwip_sanity_check()
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
/**
|
||||
* Perform Sanity check of user-configurable values, and initialize all modules.
|
||||
*/
|
||||
void
|
||||
lwip_init(void)
|
||||
{
|
||||
/* Sanity check user-configurable values */
|
||||
lwip_sanity_check();
|
||||
|
||||
/* Modules initialization */
|
||||
stats_init();
|
||||
sys_init();
|
||||
mem_init();
|
||||
memp_init();
|
||||
pbuf_init();
|
||||
netif_init();
|
||||
#if LWIP_SOCKET
|
||||
lwip_socket_init();
|
||||
#endif /* LWIP_SOCKET */
|
||||
ip_init();
|
||||
#if LWIP_ARP
|
||||
etharp_init();
|
||||
#endif /* LWIP_ARP */
|
||||
#if LWIP_RAW
|
||||
raw_init();
|
||||
#endif /* LWIP_RAW */
|
||||
#if LWIP_UDP
|
||||
udp_init();
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
tcp_init();
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_SNMP
|
||||
snmp_init();
|
||||
#endif /* LWIP_SNMP */
|
||||
#if LWIP_AUTOIP
|
||||
autoip_init();
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_IGMP
|
||||
igmp_init();
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_DNS
|
||||
dns_init();
|
||||
#endif /* LWIP_DNS */
|
||||
}
|
||||
@@ -1,497 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* AutoIP Automatic LinkLocal IP Configuration
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Dominik Spies <kontakt@dspies.de>
|
||||
*
|
||||
* This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
|
||||
* with RFC 3927.
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Dominik Spies
|
||||
* <kontakt@dspies.de>
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* USAGE:
|
||||
*
|
||||
* define LWIP_AUTOIP 1 in your lwipopts.h
|
||||
*
|
||||
* If you don't use tcpip.c (so, don't call, you don't call tcpip_init):
|
||||
* - First, call autoip_init().
|
||||
* - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces,
|
||||
* that should be defined in autoip.h.
|
||||
* I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
|
||||
* Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
|
||||
*
|
||||
* Without DHCP:
|
||||
* - Call autoip_start() after netif_add().
|
||||
*
|
||||
* With DHCP:
|
||||
* - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
|
||||
* - Configure your DHCP Client.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 169.254.0.0 */
|
||||
#define AUTOIP_NET 0xA9FE0000
|
||||
/* 169.254.1.0 */
|
||||
#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100)
|
||||
/* 169.254.254.255 */
|
||||
#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF)
|
||||
|
||||
|
||||
/** Pseudo random macro based on netif informations.
|
||||
* You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
|
||||
#ifndef LWIP_AUTOIP_RAND
|
||||
#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
|
||||
((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
|
||||
((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
|
||||
((u32_t)((netif->hwaddr[4]) & 0xff))) + \
|
||||
(netif->autoip?netif->autoip->tried_llipaddr:0))
|
||||
#endif /* LWIP_AUTOIP_RAND */
|
||||
|
||||
/**
|
||||
* Macro that generates the initial IP address to be tried by AUTOIP.
|
||||
* If you want to override this, define it to something else in lwipopts.h.
|
||||
*/
|
||||
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
|
||||
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
|
||||
htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
|
||||
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
|
||||
#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
|
||||
|
||||
/* static functions */
|
||||
static void autoip_handle_arp_conflict(struct netif *netif);
|
||||
|
||||
/* creates a pseudo random LL IP-Address for a network interface */
|
||||
static void autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
|
||||
/* sends an ARP probe */
|
||||
static err_t autoip_arp_probe(struct netif *netif);
|
||||
|
||||
/* sends an ARP announce */
|
||||
static err_t autoip_arp_announce(struct netif *netif);
|
||||
|
||||
/* configure interface for use with current LL IP-Address */
|
||||
static err_t autoip_bind(struct netif *netif);
|
||||
|
||||
/* start sending probes for llipaddr */
|
||||
static void autoip_start_probing(struct netif *netif);
|
||||
|
||||
/**
|
||||
* Initialize this module
|
||||
*/
|
||||
void
|
||||
autoip_init(void)
|
||||
{
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a IP address conflict after an ARP conflict detection
|
||||
*/
|
||||
static void
|
||||
autoip_handle_arp_conflict(struct netif *netif)
|
||||
{
|
||||
/* Somehow detect if we are defending or retreating */
|
||||
unsigned char defend = 1; /* tbd */
|
||||
|
||||
if(defend) {
|
||||
if(netif->autoip->lastconflict > 0) {
|
||||
/* retreat, there was a conflicting ARP in the last
|
||||
* DEFEND_INTERVAL seconds
|
||||
*/
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
|
||||
|
||||
/* TODO: close all TCP sessions */
|
||||
autoip_start(netif);
|
||||
} else {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
|
||||
autoip_arp_announce(netif);
|
||||
netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
|
||||
/* TODO: close all TCP sessions */
|
||||
autoip_start(netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
*
|
||||
* @param netif network interface on which create the IP-Address
|
||||
* @param ipaddr ip address to initialize
|
||||
*/
|
||||
static void
|
||||
autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
{
|
||||
/* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
* compliant to RFC 3927 Section 2.1
|
||||
* We have 254 * 256 possibilities */
|
||||
|
||||
u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
|
||||
addr += netif->autoip->tried_llipaddr;
|
||||
addr = AUTOIP_NET | (addr & 0xffff);
|
||||
/* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
|
||||
|
||||
if (addr < AUTOIP_RANGE_START) {
|
||||
addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
|
||||
}
|
||||
if (addr > AUTOIP_RANGE_END) {
|
||||
addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
|
||||
}
|
||||
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
|
||||
(addr <= AUTOIP_RANGE_END));
|
||||
ipaddr->addr = htonl(addr);
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
|
||||
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an ARP probe from a network interface
|
||||
*
|
||||
* @param netif network interface used to send the probe
|
||||
*/
|
||||
static err_t
|
||||
autoip_arp_probe(struct netif *netif)
|
||||
{
|
||||
return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast,
|
||||
(struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero,
|
||||
&netif->autoip->llipaddr, ARP_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an ARP announce from a network interface
|
||||
*
|
||||
* @param netif network interface used to send the announce
|
||||
*/
|
||||
static err_t
|
||||
autoip_arp_announce(struct netif *netif)
|
||||
{
|
||||
return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast,
|
||||
(struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero,
|
||||
&netif->autoip->llipaddr, ARP_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure interface for use with current LL IP-Address
|
||||
*
|
||||
* @param netif network interface to configure with current LL IP-Address
|
||||
*/
|
||||
static err_t
|
||||
autoip_bind(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
struct ip_addr sn_mask, gw_addr;
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr));
|
||||
|
||||
IP4_ADDR(&sn_mask, 255, 255, 0, 0);
|
||||
IP4_ADDR(&gw_addr, 0, 0, 0, 0);
|
||||
|
||||
netif_set_ipaddr(netif, &autoip->llipaddr);
|
||||
netif_set_netmask(netif, &sn_mask);
|
||||
netif_set_gw(netif, &gw_addr);
|
||||
|
||||
/* bring the interface up */
|
||||
netif_set_up(netif);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start AutoIP client
|
||||
*
|
||||
* @param netif network interface on which start the AutoIP client
|
||||
*/
|
||||
err_t
|
||||
autoip_start(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
err_t result = ERR_OK;
|
||||
|
||||
if(netif_is_up(netif)) {
|
||||
netif_set_down(netif);
|
||||
}
|
||||
|
||||
/* Set IP-Address, Netmask and Gateway to 0 to make sure that
|
||||
* ARP Packets are formed correctly
|
||||
*/
|
||||
netif->ip_addr.addr = 0;
|
||||
netif->netmask.addr = 0;
|
||||
netif->gw.addr = 0;
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
|
||||
netif->name[1], (u16_t)netif->num));
|
||||
if(autoip == NULL) {
|
||||
/* no AutoIP client attached yet? */
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_start(): starting new AUTOIP client\n"));
|
||||
autoip = mem_malloc(sizeof(struct autoip));
|
||||
if(autoip == NULL) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_start(): could not allocate autoip\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
memset( autoip, 0, sizeof(struct autoip));
|
||||
/* store this AutoIP client in the netif */
|
||||
netif->autoip = autoip;
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
|
||||
} else {
|
||||
autoip->state = AUTOIP_STATE_OFF;
|
||||
autoip->ttw = 0;
|
||||
autoip->sent_num = 0;
|
||||
memset(&autoip->llipaddr, 0, sizeof(struct ip_addr));
|
||||
autoip->lastconflict = 0;
|
||||
}
|
||||
|
||||
autoip_create_addr(netif, &(autoip->llipaddr));
|
||||
autoip->tried_llipaddr++;
|
||||
autoip_start_probing(netif);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
autoip_start_probing(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
|
||||
autoip->state = AUTOIP_STATE_PROBING;
|
||||
autoip->sent_num = 0;
|
||||
|
||||
/* time to wait to first probe, this is randomly
|
||||
* choosen out of 0 to PROBE_WAIT seconds.
|
||||
* compliant to RFC 3927 Section 2.2.1
|
||||
*/
|
||||
autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
|
||||
|
||||
/*
|
||||
* if we tried more then MAX_CONFLICTS we must limit our rate for
|
||||
* accquiring and probing address
|
||||
* compliant to RFC 3927 Section 2.2.1
|
||||
*/
|
||||
if(autoip->tried_llipaddr > MAX_CONFLICTS) {
|
||||
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a possible change in the network configuration.
|
||||
*
|
||||
* If there is an AutoIP address configured, take the interface down
|
||||
* and begin probing with the same address.
|
||||
*/
|
||||
void
|
||||
autoip_network_changed(struct netif *netif)
|
||||
{
|
||||
if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
|
||||
netif_set_down(netif);
|
||||
autoip_start_probing(netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop AutoIP client
|
||||
*
|
||||
* @param netif network interface on which stop the AutoIP client
|
||||
*/
|
||||
err_t
|
||||
autoip_stop(struct netif *netif)
|
||||
{
|
||||
netif->autoip->state = AUTOIP_STATE_OFF;
|
||||
netif_set_down(netif);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
|
||||
*/
|
||||
void
|
||||
autoip_tmr()
|
||||
{
|
||||
struct netif *netif = netif_list;
|
||||
/* loop through netif's */
|
||||
while (netif != NULL) {
|
||||
/* only act on AutoIP configured interfaces */
|
||||
if (netif->autoip != NULL) {
|
||||
if(netif->autoip->lastconflict > 0) {
|
||||
netif->autoip->lastconflict--;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
|
||||
(u16_t)(netif->autoip->state), netif->autoip->ttw));
|
||||
|
||||
switch(netif->autoip->state) {
|
||||
case AUTOIP_STATE_PROBING:
|
||||
if(netif->autoip->ttw > 0) {
|
||||
netif->autoip->ttw--;
|
||||
} else {
|
||||
if(netif->autoip->sent_num >= PROBE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||
} else {
|
||||
autoip_arp_probe(netif);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_tmr() PROBING Sent Probe\n"));
|
||||
netif->autoip->sent_num++;
|
||||
/* calculate time to wait to next probe */
|
||||
netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
|
||||
((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
|
||||
PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUTOIP_STATE_ANNOUNCING:
|
||||
if(netif->autoip->ttw > 0) {
|
||||
netif->autoip->ttw--;
|
||||
} else {
|
||||
if(netif->autoip->sent_num == 0) {
|
||||
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
|
||||
* Now we can bind to an IP address and use it.
|
||||
*
|
||||
* autoip_bind calls netif_set_up. This triggers a gratuitous ARP
|
||||
* which counts as an announcement.
|
||||
*/
|
||||
autoip_bind(netif);
|
||||
} else {
|
||||
autoip_arp_announce(netif);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_tmr() ANNOUNCING Sent Announce\n"));
|
||||
}
|
||||
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
netif->autoip->sent_num++;
|
||||
|
||||
if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_BOUND;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* proceed to next network interface */
|
||||
netif = netif->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles every incoming ARP Packet, called by etharp_arp_input.
|
||||
*
|
||||
* @param netif network interface to use for autoip processing
|
||||
* @param hdr Incoming ARP packet
|
||||
*/
|
||||
void
|
||||
autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
{
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
|
||||
if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
|
||||
/* when ip.src == llipaddr && hw.src != netif->hwaddr
|
||||
*
|
||||
* when probing ip.dst == llipaddr && hw.src != netif->hwaddr
|
||||
* we have a conflict and must solve it
|
||||
*/
|
||||
struct ip_addr sipaddr, dipaddr;
|
||||
struct eth_addr netifaddr;
|
||||
netifaddr.addr[0] = netif->hwaddr[0];
|
||||
netifaddr.addr[1] = netif->hwaddr[1];
|
||||
netifaddr.addr[2] = netif->hwaddr[2];
|
||||
netifaddr.addr[3] = netif->hwaddr[3];
|
||||
netifaddr.addr[4] = netif->hwaddr[4];
|
||||
netifaddr.addr[5] = netif->hwaddr[5];
|
||||
|
||||
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
||||
* structure packing (not using structure copy which breaks strict-aliasing rules).
|
||||
*/
|
||||
SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
|
||||
SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
|
||||
|
||||
if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
|
||||
((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
|
||||
(netif->autoip->sent_num == 0))) {
|
||||
/* RFC 3927 Section 2.2.1:
|
||||
* from beginning to after ANNOUNCE_WAIT
|
||||
* seconds we have a conflict if
|
||||
* ip.src == llipaddr OR
|
||||
* ip.dst == llipaddr && hw.src != own hwaddr
|
||||
*/
|
||||
if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
|
||||
(ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
|
||||
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("autoip_arp_reply(): Probe Conflict detected\n"));
|
||||
autoip_start(netif);
|
||||
}
|
||||
} else {
|
||||
/* RFC 3927 Section 2.5:
|
||||
* in any state we have a conflict if
|
||||
* ip.src == llipaddr && hw.src != own hwaddr
|
||||
*/
|
||||
if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
|
||||
!eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
|
||||
autoip_handle_arp_conflict(netif);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LWIP_AUTOIP */
|
||||
@@ -1,331 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* ICMP - Internet Control Message Protocol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* Some ICMP messages should be passed to the transport protocols. This
|
||||
is not implemented. */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
|
||||
* used to modify and send a response packet (and to 1 if this is not the case,
|
||||
* e.g. when link header is stripped of when receiving) */
|
||||
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
|
||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||
|
||||
/* The amount of data from the original packet to return in a dest-unreachable */
|
||||
#define ICMP_DEST_UNREACH_DATASIZE 8
|
||||
|
||||
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
||||
|
||||
/**
|
||||
* Processes ICMP input packets, called from ip_input().
|
||||
*
|
||||
* Currently only processes icmp echo requests and sends
|
||||
* out the echo response.
|
||||
*
|
||||
* @param p the icmp echo request packet, p->payload pointing to the ip header
|
||||
* @param inp the netif on which this packet was received
|
||||
*/
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
u8_t type;
|
||||
#ifdef LWIP_DEBUG
|
||||
u8_t code;
|
||||
#endif /* LWIP_DEBUG */
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
s16_t hlen;
|
||||
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
snmp_inc_icmpinmsgs();
|
||||
|
||||
|
||||
iphdr = p->payload;
|
||||
hlen = IPH_HL(iphdr) * 4;
|
||||
if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||
goto lenerr;
|
||||
}
|
||||
|
||||
type = *((u8_t *)p->payload);
|
||||
#ifdef LWIP_DEBUG
|
||||
code = *(((u8_t *)p->payload)+1);
|
||||
#endif /* LWIP_DEBUG */
|
||||
switch (type) {
|
||||
case ICMP_ECHO:
|
||||
#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
|
||||
{
|
||||
int accepted = 1;
|
||||
#if !LWIP_MULTICAST_PING
|
||||
/* multicast destination address? */
|
||||
if (ip_addr_ismulticast(&iphdr->dest)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_MULTICAST_PING */
|
||||
#if !LWIP_BROADCAST_PING
|
||||
/* broadcast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_BROADCAST_PING */
|
||||
/* broadcast or multicast destination address not acceptd? */
|
||||
if (!accepted) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||
goto lenerr;
|
||||
}
|
||||
if (inet_chksum_pbuf(p) != 0) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.chkerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
}
|
||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
|
||||
/* p is not big enough to contain link headers
|
||||
* allocate a new one and copy p into it
|
||||
*/
|
||||
struct pbuf *r;
|
||||
/* switch p->payload to ip header */
|
||||
if (pbuf_header(p, hlen)) {
|
||||
LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0);
|
||||
goto memerr;
|
||||
}
|
||||
/* allocate new packet buffer with space for link headers */
|
||||
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
|
||||
if (r == NULL) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
|
||||
goto memerr;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold struct the ICMP header",
|
||||
(r->len >= hlen + sizeof(struct icmp_echo_hdr)));
|
||||
/* copy the whole packet including ip header */
|
||||
if (pbuf_copy(r, p) != ERR_OK) {
|
||||
LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
|
||||
goto memerr;
|
||||
}
|
||||
iphdr = r->payload;
|
||||
/* switch r->payload back to icmp header */
|
||||
if (pbuf_header(r, -hlen)) {
|
||||
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
|
||||
goto memerr;
|
||||
}
|
||||
/* free the original p */
|
||||
pbuf_free(p);
|
||||
/* we now have an identical copy of p that has room for link headers */
|
||||
p = r;
|
||||
} else {
|
||||
/* restore p->payload to point to icmp header */
|
||||
if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
|
||||
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
|
||||
goto memerr;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||
/* At this point, all checks are OK. */
|
||||
/* We generate an answer by switching the dest and src ip addresses,
|
||||
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
||||
iecho = p->payload;
|
||||
tmpaddr.addr = iphdr->src.addr;
|
||||
iphdr->src.addr = iphdr->dest.addr;
|
||||
iphdr->dest.addr = tmpaddr.addr;
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
||||
/* adjust the checksum */
|
||||
if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8) + 1;
|
||||
} else {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8);
|
||||
}
|
||||
|
||||
/* Set the correct TTL and recalculate the header checksum. */
|
||||
IPH_TTL_SET(iphdr, ICMP_TTL);
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
#endif /* CHECKSUM_GEN_IP */
|
||||
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of echo replies attempted to send */
|
||||
snmp_inc_icmpoutechoreps();
|
||||
|
||||
if(pbuf_header(p, hlen)) {
|
||||
LWIP_ASSERT("Can't move over header in packet", 0);
|
||||
} else {
|
||||
err_t ret;
|
||||
ret = ip_output_if(p, &(iphdr->src), IP_HDRINCL,
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP, inp);
|
||||
if (ret != ERR_OK) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n",
|
||||
(s16_t)type, (s16_t)code));
|
||||
ICMP_STATS_INC(icmp.proterr);
|
||||
ICMP_STATS_INC(icmp.drop);
|
||||
}
|
||||
pbuf_free(p);
|
||||
return;
|
||||
lenerr:
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
memerr:
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an icmp 'destination unreachable' packet, called from ip_input() if
|
||||
* the transport layer protocol is unknown and from udp_input() if the local
|
||||
* port is not bound.
|
||||
*
|
||||
* @param p the input packet for which the 'unreachable' should be sent,
|
||||
* p->payload pointing to the IP header
|
||||
* @param t type of the 'unreachable' packet
|
||||
*/
|
||||
void
|
||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
{
|
||||
icmp_send_response(p, ICMP_DUR, t);
|
||||
}
|
||||
|
||||
#if IP_FORWARD || IP_REASSEMBLY
|
||||
/**
|
||||
* Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
|
||||
*
|
||||
* @param p the input packet for which the 'time exceeded' should be sent,
|
||||
* p->payload pointing to the IP header
|
||||
* @param t type of the 'time exceeded' packet
|
||||
*/
|
||||
void
|
||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
{
|
||||
icmp_send_response(p, ICMP_TE, t);
|
||||
}
|
||||
|
||||
#endif /* IP_FORWARD || IP_REASSEMBLY */
|
||||
|
||||
/**
|
||||
* Send an icmp packet in response to an incoming packet.
|
||||
*
|
||||
* @param p the input packet for which the 'unreachable' should be sent,
|
||||
* p->payload pointing to the IP header
|
||||
* @param type Type of the ICMP header
|
||||
* @param code Code of the ICMP header
|
||||
*/
|
||||
static void
|
||||
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
/* we can use the echo header here */
|
||||
struct icmp_echo_hdr *icmphdr;
|
||||
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||
PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||
|
||||
iphdr = p->payload;
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||
|
||||
icmphdr = q->payload;
|
||||
icmphdr->type = type;
|
||||
icmphdr->code = code;
|
||||
icmphdr->id = 0;
|
||||
icmphdr->seqno = 0;
|
||||
|
||||
/* copy fields from original packet */
|
||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
|
||||
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
||||
|
||||
/* calculate checksum */
|
||||
icmphdr->chksum = 0;
|
||||
icmphdr->chksum = inet_chksum(icmphdr, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of destination unreachable messages attempted to send */
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#endif /* LWIP_ICMP */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,278 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Functions common to all TCP/IPv4 modules, such as the byte order functions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
|
||||
/* Here for now until needed in other places in lwIP */
|
||||
#ifndef isprint
|
||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||
#define isdigit(c) in_range(c, '0', '9')
|
||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||
#define islower(c) in_range(c, 'a', 'z')
|
||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*
|
||||
* @param cp IP address in ascii represenation (e.g. "127.0.0.1")
|
||||
* @return ip address in network order
|
||||
*/
|
||||
u32_t
|
||||
inet_addr(const char *cp)
|
||||
{
|
||||
struct in_addr val;
|
||||
|
||||
if (inet_aton(cp, &val)) {
|
||||
return (val.s_addr);
|
||||
}
|
||||
return (INADDR_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*
|
||||
* @param cp IP address in ascii represenation (e.g. "127.0.0.1")
|
||||
* @param addr pointer to which to save the ip address in network order
|
||||
* @return 1 if cp could be converted to addr, 0 on failure
|
||||
*/
|
||||
int
|
||||
inet_aton(const char *cp, struct in_addr *addr)
|
||||
{
|
||||
u32_t val;
|
||||
u8_t base;
|
||||
char c;
|
||||
u32_t parts[4];
|
||||
u32_t *pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, 1-9=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
val = 0;
|
||||
base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X') {
|
||||
base = 16;
|
||||
c = *++cp;
|
||||
} else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && !isspace(c))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
switch (pp - parts + 1) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffffUL)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert numeric IP address into decimal dotted ASCII representation.
|
||||
* returns ptr to static buffer; not reentrant!
|
||||
*
|
||||
* @param addr ip address in network order to convert
|
||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||
* represenation of addr
|
||||
*/
|
||||
char *
|
||||
inet_ntoa(struct in_addr addr)
|
||||
{
|
||||
static char str[16];
|
||||
u32_t s_addr = addr.s_addr;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
|
||||
rp = str;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
do {
|
||||
rem = *ap % (u8_t)10;
|
||||
*ap /= (u8_t)10;
|
||||
inv[i++] = '0' + rem;
|
||||
} while(*ap);
|
||||
while(i--)
|
||||
*rp++ = inv[i];
|
||||
*rp++ = '.';
|
||||
ap++;
|
||||
}
|
||||
*--rp = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* These are reference implementations of the byte swapping functions.
|
||||
* Again with the aim of being simple, correct and fully portable.
|
||||
* Byte swapping is the second thing you would want to optimize. You will
|
||||
* need to port it to your architecture and in your cc.h:
|
||||
*
|
||||
* #define LWIP_PLATFORM_BYTESWAP 1
|
||||
* #define LWIP_PLATFORM_HTONS(x) <your_htons>
|
||||
* #define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
||||
*
|
||||
* Note ntohs() and ntohl() are merely references to the htonx counterparts.
|
||||
*/
|
||||
|
||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
|
||||
/**
|
||||
* Convert an u16_t from host- to network byte order.
|
||||
*
|
||||
* @param n u16_t in host byte order
|
||||
* @return n in network byte order
|
||||
*/
|
||||
u16_t
|
||||
htons(u16_t n)
|
||||
{
|
||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u16_t from network- to host byte order.
|
||||
*
|
||||
* @param n u16_t in network byte order
|
||||
* @return n in host byte order
|
||||
*/
|
||||
u16_t
|
||||
ntohs(u16_t n)
|
||||
{
|
||||
return htons(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u32_t from host- to network byte order.
|
||||
*
|
||||
* @param n u32_t in host byte order
|
||||
* @return n in network byte order
|
||||
*/
|
||||
u32_t
|
||||
htonl(u32_t n)
|
||||
{
|
||||
return ((n & 0xff) << 24) |
|
||||
((n & 0xff00) << 8) |
|
||||
((n & 0xff0000UL) >> 8) |
|
||||
((n & 0xff000000UL) >> 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u32_t from network- to host byte order.
|
||||
*
|
||||
* @param n u32_t in network byte order
|
||||
* @return n in host byte order
|
||||
*/
|
||||
u32_t
|
||||
ntohl(u32_t n)
|
||||
{
|
||||
return htonl(n);
|
||||
}
|
||||
|
||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
||||
@@ -1,438 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Incluse internet checksum functions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* These are some reference implementations of the checksum algorithm, with the
|
||||
* aim of being simple, correct and fully portable. Checksumming is the
|
||||
* first thing you would want to optimize for your platform. If you create
|
||||
* your own version, link it in and in your cc.h put:
|
||||
*
|
||||
* #define LWIP_CHKSUM <your_checksum_routine>
|
||||
*
|
||||
* Or you can select from the implementations below by defining
|
||||
* LWIP_CHKSUM_ALGORITHM to 1, 2 or 3.
|
||||
*/
|
||||
|
||||
#ifndef LWIP_CHKSUM
|
||||
# define LWIP_CHKSUM lwip_standard_chksum
|
||||
# ifndef LWIP_CHKSUM_ALGORITHM
|
||||
# define LWIP_CHKSUM_ALGORITHM 1
|
||||
# endif
|
||||
#endif
|
||||
/* If none set: */
|
||||
#ifndef LWIP_CHKSUM_ALGORITHM
|
||||
# define LWIP_CHKSUM_ALGORITHM 0
|
||||
#endif
|
||||
|
||||
/** Like the name says... */
|
||||
#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/* little endian and PLATFORM_BYTESWAP defined */
|
||||
#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
|
||||
#else
|
||||
/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */
|
||||
#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
|
||||
#endif
|
||||
|
||||
/** Split an u32_t in two u16_ts and add them up */
|
||||
#define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL))
|
||||
|
||||
#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
|
||||
/**
|
||||
* lwip checksum
|
||||
*
|
||||
* @param dataptr points to start of data to be summed at any boundary
|
||||
* @param len length of data to be summed
|
||||
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||
*
|
||||
* @note accumulator size limits summable length to 64k
|
||||
* @note host endianess is irrelevant (p3 RFC1071)
|
||||
*/
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
u16_t src;
|
||||
u8_t *octetptr;
|
||||
|
||||
acc = 0;
|
||||
/* dataptr may be at odd or even addresses */
|
||||
octetptr = (u8_t*)dataptr;
|
||||
while (len > 1) {
|
||||
/* declare first octet as most significant
|
||||
thus assume network order, ignoring host order */
|
||||
src = (*octetptr) << 8;
|
||||
octetptr++;
|
||||
/* declare second octet as least significant */
|
||||
src |= (*octetptr);
|
||||
octetptr++;
|
||||
acc += src;
|
||||
len -= 2;
|
||||
}
|
||||
if (len > 0) {
|
||||
/* accumulate remaining octet */
|
||||
src = (*octetptr) << 8;
|
||||
acc += src;
|
||||
}
|
||||
/* add deferred carry bits */
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
if ((acc & 0xffff0000UL) != 0) {
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
}
|
||||
/* This maybe a little confusing: reorder sum using htons()
|
||||
instead of ntohs() since it has a little less call overhead.
|
||||
The caller must invert bits for Internet sum ! */
|
||||
return htons((u16_t)acc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */
|
||||
/*
|
||||
* Curt McDowell
|
||||
* Broadcom Corp.
|
||||
* csm@broadcom.com
|
||||
*
|
||||
* IP checksum two bytes at a time with support for
|
||||
* unaligned buffer.
|
||||
* Works for len up to and including 0x20000.
|
||||
* by Curt McDowell, Broadcom Corp. 12/08/2005
|
||||
*
|
||||
* @param dataptr points to start of data to be summed at any boundary
|
||||
* @param len length of data to be summed
|
||||
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = dataptr;
|
||||
u16_t *ps, t = 0;
|
||||
u32_t sum = 0;
|
||||
int odd = ((u32_t)pb & 1);
|
||||
|
||||
/* Get aligned to u16_t */
|
||||
if (odd && len > 0) {
|
||||
((u8_t *)&t)[1] = *pb++;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Add the bulk of the data */
|
||||
ps = (u16_t *)pb;
|
||||
while (len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
/* Consume left-over byte, if any */
|
||||
if (len > 0) {
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;;
|
||||
}
|
||||
|
||||
/* Add end bytes */
|
||||
sum += t;
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
sum = FOLD_U32T(sum);
|
||||
sum = FOLD_U32T(sum);
|
||||
|
||||
/* Swap if alignment was odd */
|
||||
if (odd) {
|
||||
sum = SWAP_BYTES_IN_WORD(sum);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */
|
||||
/**
|
||||
* An optimized checksum routine. Basically, it uses loop-unrolling on
|
||||
* the checksum loop, treating the head and tail bytes specially, whereas
|
||||
* the inner loop acts on 8 bytes at a time.
|
||||
*
|
||||
* @arg start of buffer to be checksummed. May be an odd byte address.
|
||||
* @len number of bytes in the buffer to be checksummed.
|
||||
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||
*
|
||||
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = dataptr;
|
||||
u16_t *ps, t = 0;
|
||||
u32_t *pl;
|
||||
u32_t sum = 0, tmp;
|
||||
/* starts at odd byte address? */
|
||||
int odd = ((u32_t)pb & 1);
|
||||
|
||||
if (odd && len > 0) {
|
||||
((u8_t *)&t)[1] = *pb++;
|
||||
len--;
|
||||
}
|
||||
|
||||
ps = (u16_t *)pb;
|
||||
|
||||
if (((u32_t)ps & 3) && len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
pl = (u32_t *)ps;
|
||||
|
||||
while (len > 7) {
|
||||
tmp = sum + *pl++; /* ping */
|
||||
if (tmp < sum) {
|
||||
tmp++; /* add back carry */
|
||||
}
|
||||
|
||||
sum = tmp + *pl++; /* pong */
|
||||
if (sum < tmp) {
|
||||
sum++; /* add back carry */
|
||||
}
|
||||
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* make room in upper bits */
|
||||
sum = FOLD_U32T(sum);
|
||||
|
||||
ps = (u16_t *)pl;
|
||||
|
||||
/* 16-bit aligned word remaining? */
|
||||
while (len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
/* dangling tail byte remaining? */
|
||||
if (len > 0) { /* include odd byte */
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;
|
||||
}
|
||||
|
||||
sum += t; /* add end bytes */
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
sum = FOLD_U32T(sum);
|
||||
sum = FOLD_U32T(sum);
|
||||
|
||||
if (odd) {
|
||||
sum = SWAP_BYTES_IN_WORD(sum);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
* IP addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ip address (used for checksum of pseudo header)
|
||||
* @param dst destination ip address (used for checksum of pseudo header)
|
||||
* @param proto ip protocol (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
(void *)q, (void *)q->next));
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
/* just executing this next line is probably faster that the if statement needed
|
||||
to check whether we really need to execute it, and does no harm */
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
acc += (dest->addr & 0xffffUL);
|
||||
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
* IP addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ip address (used for checksum of pseudo header)
|
||||
* @param dst destination ip address (used for checksum of pseudo header)
|
||||
* @param proto ip protocol (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
/* Currently only used by UDPLITE, although this could change in the future. */
|
||||
#if LWIP_UDPLITE
|
||||
u16_t
|
||||
inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
u16_t chklen;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
(void *)q, (void *)q->next));
|
||||
chklen = q->len;
|
||||
if (chklen > chksum_len) {
|
||||
chklen = chksum_len;
|
||||
}
|
||||
acc += LWIP_CHKSUM(q->payload, chklen);
|
||||
chksum_len -= chklen;
|
||||
LWIP_ASSERT("delete me", chksum_len < 0x7fff);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
/* fold the upper bit down */
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
acc += (dest->addr & 0xffffUL);
|
||||
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
#endif /* LWIP_UDPLITE */
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
||||
* and ICMP.
|
||||
*
|
||||
* @param dataptr start of the buffer to calculate the checksum (no alignment needed)
|
||||
* @param len length of the buffer to calculate the checksum
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
return ~LWIP_CHKSUM(dataptr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a checksum over a chain of pbufs (without pseudo-header, much like
|
||||
* inet_chksum only pbufs are used).
|
||||
*
|
||||
* @param p pbuf chain over that the checksum should be calculated
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
inet_chksum_pbuf(struct pbuf *p)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user