static int _rti_iterator_arg_empty_init(_rti_iterator_arg _param) { int x = 0; int y = 0; _param->empty.values = rtalloc(sizeof(double *) * _param->dimension.rows); _param->empty.nodata = rtalloc(sizeof(int *) * _param->dimension.rows); if (_param->empty.values == NULL || _param->empty.nodata == NULL) { rterror("_rti_iterator_arg_empty_init: Could not allocate memory for empty values and NODATA"); return 0; } for (y = 0; y < _param->dimension.rows; y++) { _param->empty.values[y] = rtalloc(sizeof(double) * _param->dimension.columns); _param->empty.nodata[y] = rtalloc(sizeof(int) * _param->dimension.columns); if (_param->empty.values[y] == NULL || _param->empty.nodata[y] == NULL) { rterror("_rti_iterator_arg_empty_init: Could not allocate memory for elements of empty values and NODATA"); return 0; } for (x = 0; x < _param->dimension.columns; x++) { _param->empty.values[y][x] = 0; _param->empty.nodata[y][x] = 1; } } return 1; }
rt_band cu_add_band(rt_raster raster, rt_pixtype pixtype, int hasnodata, double nodataval) { void* mem = NULL; int32_t bandNum = 0; size_t datasize = 0; rt_band band = NULL; uint16_t width = 0; uint16_t height = 0; width = rt_raster_get_width(raster); height = rt_raster_get_height(raster); datasize = rt_pixtype_size(pixtype) * width * height; mem = rtalloc(datasize); CU_ASSERT(mem != NULL); if (hasnodata) memset(mem, nodataval, datasize); else memset(mem, 0, datasize); band = rt_band_new_inline(width, height, pixtype, hasnodata, nodataval, mem); CU_ASSERT(band != NULL); rt_band_set_ownsdata_flag(band, 1); bandNum = rt_raster_add_band(raster, band, rt_raster_get_num_bands(raster)); CU_ASSERT(bandNum >= 0); return band; }
static _rti_colormap_arg _rti_colormap_arg_init(rt_raster raster) { _rti_colormap_arg arg = NULL; arg = rtalloc(sizeof(struct _rti_colormap_arg_t)); if (arg == NULL) { rterror("_rti_colormap_arg_init: Could not allocate memory for _rti_color_arg"); return NULL; } arg->band = NULL; arg->nodataentry = NULL; arg->hasnodata = 0; arg->nodataval = 0; if (raster == NULL) arg->raster = NULL; /* raster provided */ else { arg->raster = rt_raster_clone(raster, 0); if (arg->raster == NULL) { rterror("_rti_colormap_arg_init: Could not create output raster"); return NULL; } } arg->nexpr = 0; arg->expr = NULL; arg->npos = 0; arg->pos = NULL; return arg; }
static void test_raster_replace_band() { rt_raster raster; rt_band band; rt_band rband; void* mem; size_t datasize; uint16_t width; uint16_t height; double nodata; raster = rt_raster_new(10, 10); CU_ASSERT(raster != NULL); /* or we're out of virtual memory */ band = cu_add_band(raster, PT_8BUI, 0, 0); CU_ASSERT(band != NULL); band = cu_add_band(raster, PT_8BUI, 1, 255); CU_ASSERT(band != NULL); width = rt_raster_get_width(raster); height = rt_raster_get_height(raster); datasize = rt_pixtype_size(PT_8BUI) * width * height; mem = rtalloc(datasize); band = rt_band_new_inline(width, height, PT_8BUI, 1, 1, mem); CU_ASSERT(band != NULL); rt_band_set_ownsdata_flag(band, 1); rband = rt_raster_replace_band(raster, band, 0); CU_ASSERT(rband != NULL); rt_band_get_nodata(rt_raster_get_band(raster, 0), &nodata); CU_ASSERT_DOUBLE_EQUAL(nodata, 1, DBL_EPSILON); rt_band_destroy(rband); cu_free_raster(raster); }
static int _rti_iterator_arg_callback_init(_rti_iterator_arg _param) { int i = 0; _param->arg = rtalloc(sizeof(struct rt_iterator_arg_t)); if (_param->arg == NULL) { rterror("_rti_iterator_arg_callback_init: Could not allocate memory for rt_iterator_arg"); return 0; } _param->arg->values = NULL; _param->arg->nodata = NULL; _param->arg->src_pixel = NULL; /* initialize argument components */ _param->arg->values = rtalloc(sizeof(double **) * _param->count); _param->arg->nodata = rtalloc(sizeof(int **) * _param->count); _param->arg->src_pixel = rtalloc(sizeof(int *) * _param->count); if (_param->arg->values == NULL || _param->arg->nodata == NULL || _param->arg->src_pixel == NULL) { rterror("_rti_iterator_arg_callback_init: Could not allocate memory for element of rt_iterator_arg"); return 0; } memset(_param->arg->values, 0, sizeof(double **) * _param->count); memset(_param->arg->nodata, 0, sizeof(int **) * _param->count); /* initialize pos */ for (i = 0; i < _param->count; i++) { _param->arg->src_pixel[i] = rtalloc(sizeof(int) * 2); if (_param->arg->src_pixel[i] == NULL) { rterror("_rti_iterator_arg_callback_init: Could not allocate memory for position elements of rt_iterator_arg"); return 0; } memset(_param->arg->src_pixel[i], 0, sizeof(int) * 2); } _param->arg->rasters = _param->count; _param->arg->rows = _param->dimension.rows; _param->arg->columns = _param->dimension.columns; _param->arg->dst_pixel[0] = 0; _param->arg->dst_pixel[1] = 0; return 1; }
static void test_gdal_rasterize() { rt_raster raster; char srs[] = "PROJCS[\"unnamed\",GEOGCS[\"unnamed ellipse\",DATUM[\"unknown\",SPHEROID[\"unnamed\",6370997,0]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],PARAMETER[\"latitude_of_center\",45],PARAMETER[\"longitude_of_center\",-100],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1],AUTHORITY[\"EPSG\",\"2163\"]]"; const char wkb_hex[] = "010300000001000000050000000000000080841ec100000000600122410000000080841ec100000000804f22410000000040e81dc100000000804f22410000000040e81dc100000000600122410000000080841ec10000000060012241"; const char *pos = wkb_hex; unsigned char *wkb = NULL; int wkb_len = 0; int i; double scale_x = 100; double scale_y = -100; rt_pixtype pixtype[] = {PT_8BUI}; double init[] = {0}; double value[] = {1}; double nodata[] = {0}; uint8_t nodata_mask[] = {1}; /* hex to byte */ wkb_len = (int) ceil(((double) strlen(wkb_hex)) / 2); wkb = (unsigned char *) rtalloc(sizeof(unsigned char) * wkb_len); for (i = 0; i < wkb_len; i++) { sscanf(pos, "%2hhx", &wkb[i]); pos += 2; } raster = rt_raster_gdal_rasterize( wkb, wkb_len, srs, 1, pixtype, init, value, nodata, nodata_mask, NULL, NULL, &scale_x, &scale_y, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); CU_ASSERT(raster != NULL); CU_ASSERT_EQUAL(rt_raster_get_width(raster), 100); CU_ASSERT_EQUAL(rt_raster_get_height(raster), 100); CU_ASSERT_NOT_EQUAL(rt_raster_get_num_bands(raster), 0); CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), -500000, DBL_EPSILON); CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 600000, DBL_EPSILON); rtdealloc(wkb); cu_free_raster(raster); }
static void mpls_forward(struct mbuf *m) { struct sockaddr_mpls *smpls; struct mpls *mpls; struct route *cache_rt = &mplsforward_rt[mycpuid]; mpls_label_t label; struct ifnet *ifp; struct sockaddr *dst; int error; KASSERT(m->m_len >= sizeof(struct mpls), ("mpls_forward: mpls header not in one mbuf")); mpls = mtod(m, struct mpls *); label = MPLS_LABEL(ntohl(mpls->mpls_shim)); smpls = (struct sockaddr_mpls *) &cache_rt->ro_dst; if (cache_rt->ro_rt == NULL || smpls->smpls_label != label) { if (cache_rt->ro_rt != NULL) { RTFREE(cache_rt->ro_rt); cache_rt->ro_rt = NULL; } smpls->smpls_family = AF_MPLS; smpls->smpls_len = sizeof(struct sockaddr_mpls); smpls->smpls_label = htonl(label); rtalloc(cache_rt); if (cache_rt->ro_rt == NULL) { /* route not found */ return; } } ifp = cache_rt->ro_rt->rt_ifp; dst = cache_rt->ro_rt->rt_gateway; error = mpls_output(m, cache_rt->ro_rt); if (error) goto bad; error = (*ifp->if_output)(ifp, m, dst, cache_rt->ro_rt); if (error) goto bad; mplsstat.mplss_forwarded++; return; bad: m_freem(m); }
static _rti_iterator_arg _rti_iterator_arg_init() { _rti_iterator_arg _param; _param = rtalloc(sizeof(struct _rti_iterator_arg_t)); if (_param == NULL) { rterror("_rti_iterator_arg_init: Could not allocate memory for _rti_iterator_arg"); return NULL; } _param->count = 0; _param->raster = NULL; _param->isempty = NULL; _param->offset = NULL; _param->width = NULL; _param->height = NULL; _param->band.rtband = NULL; _param->band.hasnodata = NULL; _param->band.isnodata = NULL; _param->band.nodataval = NULL; _param->band.minval = NULL; _param->distance.x = 0; _param->distance.y = 0; _param->dimension.rows = 0; _param->dimension.columns = 0; _param->empty.values = NULL; _param->empty.nodata = NULL; _param->arg = NULL; return _param; }
/* * Return an IPv6 address, which is the most appropriate for a given * destination and user specified options. * If necessary, this function lookups the routing table and returns * an entry to the caller for later use. */ int in6_selectsrc(struct in6_addr **in6src, struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, struct ip6_moptions *mopts, struct route_in6 *ro, struct in6_addr *laddr, u_int rtableid) { struct ifnet *ifp = NULL; struct in6_addr *dst; struct in6_ifaddr *ia6 = NULL; struct in6_pktinfo *pi = NULL; int error; dst = &dstsock->sin6_addr; /* * If the source address is explicitly specified by the caller, * check if the requested source address is indeed a unicast address * assigned to the node, and can be used as the packet's source * address. If everything is okay, use the address as source. */ if (opts && (pi = opts->ip6po_pktinfo) && !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) { struct sockaddr_in6 sa6; /* get the outgoing interface */ error = in6_selectif(dstsock, opts, mopts, ro, &ifp, rtableid); if (error) return (error); bzero(&sa6, sizeof(sa6)); sa6.sin6_family = AF_INET6; sa6.sin6_len = sizeof(sa6); sa6.sin6_addr = pi->ipi6_addr; if (ifp && IN6_IS_SCOPE_EMBED(&sa6.sin6_addr)) sa6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); if_put(ifp); /* put reference from in6_selectif */ ia6 = ifatoia6(ifa_ifwithaddr(sin6tosa(&sa6), rtableid)); if (ia6 == NULL || (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) return (EADDRNOTAVAIL); pi->ipi6_addr = sa6.sin6_addr; /* XXX: this overrides pi */ *in6src = &pi->ipi6_addr; return (0); } /* * If the source address is not specified but the socket(if any) * is already bound, use the bound address. */ if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) { *in6src = laddr; return (0); } /* * If the caller doesn't specify the source address but * the outgoing interface, use an address associated with * the interface. */ if (pi && pi->ipi6_ifindex) { ifp = if_get(pi->ipi6_ifindex); if (ifp == NULL) return (ENXIO); /* XXX: better error? */ ia6 = in6_ifawithscope(ifp, dst, rtableid); if_put(ifp); if (ia6 == NULL) return (EADDRNOTAVAIL); *in6src = &ia6->ia_addr.sin6_addr; return (0); } /* * If the destination address is a link-local unicast address or * a link/interface-local multicast address, and if the outgoing * interface is specified by the sin6_scope_id filed, use an address * associated with the interface. * XXX: We're now trying to define more specific semantics of * sin6_scope_id field, so this part will be rewritten in * the near future. */ if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MC_LINKLOCAL(dst) || IN6_IS_ADDR_MC_INTFACELOCAL(dst)) && dstsock->sin6_scope_id) { ifp = if_get(dstsock->sin6_scope_id); if (ifp == NULL) return (ENXIO); /* XXX: better error? */ ia6 = in6_ifawithscope(ifp, dst, rtableid); if_put(ifp); if (ia6 == NULL) return (EADDRNOTAVAIL); *in6src = &ia6->ia_addr.sin6_addr; return (0); } /* * If the destination address is a multicast address and * the outgoing interface for the address is specified * by the caller, use an address associated with the interface. * Even if the outgoing interface is not specified, we also * choose a loopback interface as the outgoing interface. */ if (IN6_IS_ADDR_MULTICAST(dst)) { ifp = mopts ? if_get(mopts->im6o_ifidx) : NULL; if (!ifp && dstsock->sin6_scope_id) ifp = if_get(htons(dstsock->sin6_scope_id)); if (ifp) { ia6 = in6_ifawithscope(ifp, dst, rtableid); if_put(ifp); if (ia6 == NULL) return (EADDRNOTAVAIL); *in6src = &ia6->ia_addr.sin6_addr; return (0); } } /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ if (ro) { if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid != rtableid) || !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) { rtfree(ro->ro_rt); ro->ro_rt = NULL; } if (ro->ro_rt == NULL) { struct sockaddr_in6 *sa6; /* No route yet, so try to acquire one */ bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); ro->ro_tableid = rtableid; sa6 = &ro->ro_dst; sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); sa6->sin6_addr = *dst; sa6->sin6_scope_id = dstsock->sin6_scope_id; ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst), RT_RESOLVE, ro->ro_tableid); } /* * in_pcbconnect() checks out IFF_LOOPBACK to skip using * the address. But we don't know why it does so. * It is necessary to ensure the scope even for lo0 * so doesn't check out IFF_LOOPBACK. */ if (ro->ro_rt) { ifp = if_get(ro->ro_rt->rt_ifidx); if (ifp != NULL) { ia6 = in6_ifawithscope(ifp, dst, rtableid); if_put(ifp); } if (ia6 == NULL) /* xxx scope error ?*/ ia6 = ifatoia6(ro->ro_rt->rt_ifa); } if (ia6 == NULL) return (EHOSTUNREACH); /* no route */ *in6src = &ia6->ia_addr.sin6_addr; return (0); } return (EADDRNOTAVAIL); }
int in_pcbladdr(struct inpcb *inp, struct mbuf *nam, struct sockaddr_in **plocal_sin) { struct in_ifaddr *ia; register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); if (nam->m_len != sizeof (*sin)) return (EINVAL); if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); if (sin->sin_port == 0) return (EADDRNOTAVAIL); if (in_ifaddr) { /* * If the destination address is INADDR_ANY, * use the primary local address. * If the supplied address is INADDR_BROADCAST, * and the primary interface supports broadcast, * choose the broadcast address for that interface. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) #define sintosa(sin) ((struct sockaddr *)(sin)) #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) if (sin->sin_addr.s_addr == INADDR_ANY) sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr; else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST)) sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr; } if (inp->inp_laddr.s_addr == INADDR_ANY) { register struct route *ro; ia = (struct in_ifaddr *)0; /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ ro = &inp->inp_route; if (ro->ro_rt && (satosin(&ro->ro_dst)->sin_addr.s_addr != sin->sin_addr.s_addr || inp->inp_socket->so_options & SO_DONTROUTE)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || ro->ro_rt->rt_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_INET; ro->ro_dst.sa_len = sizeof(struct sockaddr_in); ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sin->sin_addr; rtalloc(ro); } /* * If we found a route, use the address * corresponding to the outgoing interface * unless it is the loopback (in case a route * to our address on another net goes to loopback). */ if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) ia = ifatoia(ro->ro_rt->rt_ifa); if (ia == 0) { u_short fport = sin->sin_port; sin->sin_port = 0; ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); if (ia == 0) ia = ifatoia(ifa_ifwithnet(sintosa(sin))); sin->sin_port = fport; if (ia == 0) ia = in_ifaddr; if (ia == 0) return (EADDRNOTAVAIL); } /* * If the destination address is multicast and an outgoing * interface has been set as a multicast option, use the * address of that interface as our source address. */ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && inp->inp_moptions != NULL) { struct ip_moptions *imo; struct ifnet *ifp; imo = inp->inp_moptions; if (imo->imo_multicast_ifp != NULL) { ifp = imo->imo_multicast_ifp; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == 0) return (EADDRNOTAVAIL); } } /* * Don't do pcblookup call here; return interface in plocal_sin * and exit to caller, that will do the lookup. */ *plocal_sin = &ia->ia_addr; } return(0); }
int ipx_outputfl(struct mbuf *m0, struct route *ro, int flags) { struct ipx *ipx = mtod(m0, struct ipx *); struct ifnet *ifp = NULL; int error = 0; struct sockaddr_ipx *dst; struct route ipxroute; /* * Route packet. */ if (ro == NULL) { ro = &ipxroute; bzero((caddr_t)ro, sizeof(*ro)); } dst = (struct sockaddr_ipx *)&ro->ro_dst; if (ro->ro_rt == NULL) { dst->sipx_family = AF_IPX; dst->sipx_len = sizeof(*dst); dst->sipx_addr = ipx->ipx_dna; dst->sipx_addr.x_port = 0; /* * If routing to interface only, * short circuit routing lookup. */ if (flags & IPX_ROUTETOIF) { struct ipx_ifaddr *ia = ipx_iaonnetof(&ipx->ipx_dna); if (ia == NULL) { ipxstat.ipxs_noroute++; error = ENETUNREACH; goto bad; } ifp = ia->ia_ifp; goto gotif; } rtalloc(ro); } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { /* * The old route has gone away; try for a new one. */ rtfree(ro->ro_rt); ro->ro_rt = NULL; rtalloc(ro); } if (ro->ro_rt == NULL || (ifp = ro->ro_rt->rt_ifp) == NULL) { ipxstat.ipxs_noroute++; error = ENETUNREACH; goto bad; } ro->ro_rt->rt_use++; if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) dst = (struct sockaddr_ipx *)ro->ro_rt->rt_gateway; gotif: /* * Look for multicast addresses and * and verify user is allowed to send * such a packet. */ if (dst->sipx_addr.x_host.c_host[0]&1) { if ((ifp->if_flags & (IFF_BROADCAST | IFF_LOOPBACK)) == 0) { error = EADDRNOTAVAIL; goto bad; } if ((flags & IPX_ALLOWBROADCAST) == 0) { error = EACCES; goto bad; } m0->m_flags |= M_BCAST; } if (htons(ipx->ipx_len) <= ifp->if_mtu) { ipxstat.ipxs_localout++; if (ipx_copy_output) { ipx_watch_output(m0, ifp); } error = ifp->if_output(ifp, m0, (struct sockaddr *)dst, ro->ro_rt); goto done; } else { ipxstat.ipxs_mtutoosmall++; error = EMSGSIZE; } bad: if (ipx_copy_output) { ipx_watch_output(m0, ifp); } m_freem(m0); done: if (ro == &ipxroute && (flags & IPX_ROUTETOIF) == 0 && ro->ro_rt != NULL) { RTFREE(ro->ro_rt); ro->ro_rt = NULL; } return (error); }
/** * n-raster iterator. * The raster returned should be freed by the caller * * @param itrset : set of rt_iterator objects. * @param itrcount : number of objects in itrset. * @param extenttype : type of extent for the output raster. * @param customextent : raster specifying custom extent. * is only used if extenttype is ET_CUSTOM. * @param pixtype : the desired pixel type of the output raster's band. * @param hasnodata : indicates if the band has nodata value * @param nodataval : the nodata value, will be appropriately * truncated to fit the pixtype size. * @param distancex : the number of pixels around the specified pixel * along the X axis * @param distancey : the number of pixels around the specified pixel * along the Y axis * @param mask : the object of mask * @param userarg : pointer to any argument that is passed as-is to callback. * @param callback : callback function for actual processing of pixel values. * @param *rtnraster : return one band raster from iterator process * * The callback function _must_ have the following signature. * * int FNAME(rt_iterator_arg arg, void *userarg, double *value, int *nodata) * * The callback function _must_ return zero (error) or non-zero (success) * indicating whether the function ran successfully. * The parameters passed to the callback function are as follows. * * - rt_iterator_arg arg: struct containing pixel values, NODATA flags and metadata * - void *userarg: NULL or calling function provides to rt_raster_iterator() for use by callback function * - double *value: value of pixel to be burned by rt_raster_iterator() * - int *nodata: flag (0 or 1) indicating that pixel to be burned is NODATA * * @return ES_NONE on success, ES_ERROR on error */ rt_errorstate rt_raster_iterator( rt_iterator itrset, uint16_t itrcount, rt_extenttype extenttype, rt_raster customextent, rt_pixtype pixtype, uint8_t hasnodata, double nodataval, uint16_t distancex, uint16_t distancey, rt_mask mask, void *userarg, int (*callback)( rt_iterator_arg arg, void *userarg, double *value, int *nodata ), rt_raster *rtnraster ) { /* output raster */ rt_raster rtnrast = NULL; /* output raster's band */ rt_band rtnband = NULL; /* working raster */ rt_raster rast = NULL; _rti_iterator_arg _param = NULL; int allnull = 0; int allempty = 0; int aligned = 0; double offset[4] = {0.}; rt_pixel npixels; int i = 0; int status = 0; int inextent = 0; int x = 0; int y = 0; int _x = 0; int _y = 0; int _width = 0; int _height = 0; double minval; double value; int isnodata; int nodata; RASTER_DEBUG(3, "Starting..."); assert(itrset != NULL && itrcount > 0); assert(rtnraster != NULL); /* init rtnraster to NULL */ *rtnraster = NULL; /* check that callback function is not NULL */ if (callback == NULL) { rterror("rt_raster_iterator: Callback function not provided"); return ES_ERROR; } /* check that custom extent is provided if extenttype = ET_CUSTOM */ if (extenttype == ET_CUSTOM && rt_raster_is_empty(customextent)) { rterror("rt_raster_iterator: Custom extent cannot be empty if extent type is ET_CUSTOM"); return ES_ERROR; } /* check that pixtype != PT_END */ if (pixtype == PT_END) { rterror("rt_raster_iterator: Pixel type cannot be PT_END"); return ES_ERROR; } /* initialize _param */ if ((_param = _rti_iterator_arg_init()) == NULL) { rterror("rt_raster_iterator: Could not initialize internal variables"); return ES_ERROR; } /* fill _param */ if (!_rti_iterator_arg_populate(_param, itrset, itrcount, distancex, distancey, &allnull, &allempty)) { rterror("rt_raster_iterator: Could not populate for internal variables"); _rti_iterator_arg_destroy(_param); return ES_ERROR; } /* shortcut if all null, return NULL */ if (allnull == itrcount) { RASTER_DEBUG(3, "all rasters are NULL, returning NULL"); _rti_iterator_arg_destroy(_param); return ES_NONE; } /* shortcut if all empty, return empty raster */ else if (allempty == itrcount) { RASTER_DEBUG(3, "all rasters are empty, returning empty raster"); _rti_iterator_arg_destroy(_param); rtnrast = rt_raster_new(0, 0); if (rtnrast == NULL) { rterror("rt_raster_iterator: Could not create empty raster"); return ES_ERROR; } rt_raster_set_scale(rtnrast, 0, 0); *rtnraster = rtnrast; return ES_NONE; } /* check that all rasters are aligned */ RASTER_DEBUG(3, "checking alignment of all rasters"); rast = NULL; /* find raster to use as reference */ /* use custom if provided */ if (extenttype == ET_CUSTOM) { RASTER_DEBUG(4, "using custom extent as reference raster"); rast = customextent; } /* use first valid one in _param->raster */ else { for (i = 0; i < itrcount; i++) { if (!_param->isempty[i]) { RASTER_DEBUGF(4, "using raster at index %d as reference raster", i); rast = _param->raster[i]; break; } } } /* no rasters found, SHOULD NEVER BE HERE! */ if (rast == NULL) { rterror("rt_raster_iterator: Could not find reference raster to use for alignment tests"); _rti_iterator_arg_destroy(_param); return ES_ERROR; } do { aligned = 1; /* check custom first if set. also skip if rasters are the same */ if (extenttype == ET_CUSTOM && rast != customextent) { if (rt_raster_same_alignment(rast, customextent, &aligned, NULL) != ES_NONE) { rterror("rt_raster_iterator: Could not test for alignment between reference raster and custom extent"); _rti_iterator_arg_destroy(_param); return ES_ERROR; } RASTER_DEBUGF(5, "custom extent alignment: %d", aligned); if (!aligned) break; } for (i = 0; i < itrcount; i++) { /* skip NULL rasters and if rasters are the same */ if (_param->isempty[i] || rast == _param->raster[i]) continue; if (rt_raster_same_alignment(rast, _param->raster[i], &aligned, NULL) != ES_NONE) { rterror("rt_raster_iterator: Could not test for alignment between reference raster and raster %d", i); _rti_iterator_arg_destroy(_param); return ES_ERROR; } RASTER_DEBUGF(5, "raster at index %d alignment: %d", i, aligned); /* abort checking since a raster isn't aligned */ if (!aligned) break; } } while (0); /* not aligned, error */ if (!aligned) { rterror("rt_raster_iterator: The set of rasters provided (custom extent included, if appropriate) do not have the same alignment"); _rti_iterator_arg_destroy(_param); return ES_ERROR; } /* use extenttype to build output raster (no bands though) */ i = -1; switch (extenttype) { case ET_INTERSECTION: case ET_UNION: /* make copy of first "real" raster */ rtnrast = rtalloc(sizeof(struct rt_raster_t)); if (rtnrast == NULL) { rterror("rt_raster_iterator: Could not allocate memory for output raster"); _rti_iterator_arg_destroy(_param); return ES_ERROR; } for (i = 0; i < itrcount; i++) { if (!_param->isempty[i]) { memcpy(rtnrast, _param->raster[i], sizeof(struct rt_raster_serialized_t)); break; } } rtnrast->numBands = 0; rtnrast->bands = NULL; /* get extent of output raster */ rast = NULL; for (i = i + 1; i < itrcount; i++) { if (_param->isempty[i]) continue; status = rt_raster_from_two_rasters(rtnrast, _param->raster[i], extenttype, &rast, NULL); rtdealloc(rtnrast); if (rast == NULL || status != ES_NONE) { rterror("rt_raster_iterator: Could not compute %s extent of rasters", extenttype == ET_UNION ? "union" : "intersection" ); _rti_iterator_arg_destroy(_param); return ES_ERROR; } else if (rt_raster_is_empty(rast)) { rtinfo("rt_raster_iterator: Computed raster for %s extent is empty", extenttype == ET_UNION ? "union" : "intersection" ); _rti_iterator_arg_destroy(_param); *rtnraster = rast; return ES_NONE; } rtnrast = rast; rast = NULL; } break; /* first, second and last have similar checks and continue into custom */ case ET_FIRST: i = 0; case ET_SECOND: if (i < 0) { if (itrcount < 2) i = 0; else i = 1; } case ET_LAST: if (i < 0) i = itrcount - 1; /* input raster is null, return NULL */ if (_param->raster[i] == NULL) { RASTER_DEBUGF(3, "returning NULL as %s raster is NULL and extent type is ET_%s", (i == 0 ? "first" : (i == 1 ? "second" : "last")), (i == 0 ? "FIRST" : (i == 1 ? "SECOND" : "LAST")) ); _rti_iterator_arg_destroy(_param); return ES_NONE; } /* input raster is empty, return empty raster */ else if (_param->isempty[i]) { RASTER_DEBUGF(3, "returning empty raster as %s raster is empty and extent type is ET_%s", (i == 0 ? "first" : (i == 1 ? "second" : "last")), (i == 0 ? "FIRST" : (i == 1 ? "SECOND" : "LAST")) ); _rti_iterator_arg_destroy(_param); rtnrast = rt_raster_new(0, 0); if (rtnrast == NULL) { rterror("rt_raster_iterator: Could not create empty raster"); return ES_ERROR; } rt_raster_set_scale(rtnrast, 0, 0); *rtnraster = rtnrast; return ES_NONE; } /* copy the custom extent raster */ case ET_CUSTOM: rtnrast = rtalloc(sizeof(struct rt_raster_t)); if (rtnrast == NULL) { rterror("rt_raster_iterator: Could not allocate memory for output raster"); _rti_iterator_arg_destroy(_param); return ES_ERROR; } switch (extenttype) { case ET_CUSTOM: memcpy(rtnrast, customextent, sizeof(struct rt_raster_serialized_t)); break; /* first, second, last */ default: memcpy(rtnrast, _param->raster[i], sizeof(struct rt_raster_serialized_t)); break; } rtnrast->numBands = 0; rtnrast->bands = NULL; break; } _width = rt_raster_get_width(rtnrast); _height = rt_raster_get_height(rtnrast); RASTER_DEBUGF(4, "rtnrast (width, height, ulx, uly, scalex, scaley, skewx, skewy, srid) = (%d, %d, %f, %f, %f, %f, %f, %f, %d)", _width, _height, rt_raster_get_x_offset(rtnrast), rt_raster_get_y_offset(rtnrast), rt_raster_get_x_scale(rtnrast), rt_raster_get_y_scale(rtnrast), rt_raster_get_x_skew(rtnrast), rt_raster_get_y_skew(rtnrast), rt_raster_get_srid(rtnrast) ); /* init values and NODATA for use with empty rasters */ if (!_rti_iterator_arg_empty_init(_param)) { rterror("rt_raster_iterator: Could not initialize empty values and NODATA"); _rti_iterator_arg_destroy(_param); rt_raster_destroy(rtnrast); return ES_ERROR; } /* create output band */ if (rt_raster_generate_new_band( rtnrast, pixtype, nodataval, hasnodata, nodataval, 0 ) < 0) { rterror("rt_raster_iterator: Could not add new band to output raster"); _rti_iterator_arg_destroy(_param); rt_raster_destroy(rtnrast); return ES_ERROR; } /* get output band */ rtnband = rt_raster_get_band(rtnrast, 0); if (rtnband == NULL) { rterror("rt_raster_iterator: Could not get new band from output raster"); _rti_iterator_arg_destroy(_param); rt_raster_destroy(rtnrast); return ES_ERROR; } /* output band's minimum value */ minval = rt_band_get_min_value(rtnband); /* initialize argument for callback function */ if (!_rti_iterator_arg_callback_init(_param)) { rterror("rt_raster_iterator: Could not initialize callback function argument"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } /* fill _param->offset */ for (i = 0; i < itrcount; i++) { if (_param->isempty[i]) continue; status = rt_raster_from_two_rasters(rtnrast, _param->raster[i], ET_FIRST, &rast, offset); rtdealloc(rast); if (status != ES_NONE) { rterror("rt_raster_iterator: Could not compute raster offsets"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } _param->offset[i][0] = offset[2]; _param->offset[i][1] = offset[3]; RASTER_DEBUGF(4, "rast %d offset: %f %f", i, offset[2], offset[3]); } /* loop over each pixel (POI) of output raster */ /* _x,_y are for output raster */ /* x,y are for input raster */ for (_y = 0; _y < _height; _y++) { for (_x = 0; _x < _width; _x++) { RASTER_DEBUGF(4, "iterating output pixel (x, y) = (%d, %d)", _x, _y); _param->arg->dst_pixel[0] = _x; _param->arg->dst_pixel[1] = _y; /* loop through each input raster */ for (i = 0; i < itrcount; i++) { RASTER_DEBUGF(4, "raster %d", i); /* empty raster OR band does not exist and flag set to use NODATA OR band is NODATA */ if ( _param->isempty[i] || (_param->band.rtband[i] == NULL && itrset[i].nbnodata) || _param->band.isnodata[i] ) { RASTER_DEBUG(4, "empty raster, band does not exist or band is NODATA. using empty values and NODATA"); x = _x; y = _y; _param->arg->values[i] = _param->empty.values; _param->arg->nodata[i] = _param->empty.nodata; continue; } /* input raster's X,Y */ x = _x - (int) _param->offset[i][0]; y = _y - (int) _param->offset[i][1]; RASTER_DEBUGF(4, "source pixel (x, y) = (%d, %d)", x, y); _param->arg->src_pixel[i][0] = x; _param->arg->src_pixel[i][1] = y; /* neighborhood */ npixels = NULL; status = 0; if (distancex > 0 && distancey > 0) { RASTER_DEBUG(4, "getting neighborhood"); status = rt_band_get_nearest_pixel( _param->band.rtband[i], x, y, distancex, distancey, 1, &npixels ); if (status < 0) { rterror("rt_raster_iterator: Could not get pixel neighborhood"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } } /* get value of POI */ /* get pixel's value */ if ( (x >= 0 && x < _param->width[i]) && (y >= 0 && y < _param->height[i]) ) { RASTER_DEBUG(4, "getting value of POI"); if (rt_band_get_pixel( _param->band.rtband[i], x, y, &value, &isnodata ) != ES_NONE) { rterror("rt_raster_iterator: Could not get the pixel value of band"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } inextent = 1; } /* outside band extent, set to NODATA */ else { RASTER_DEBUG(4, "Outside band extent, setting value to NODATA"); /* has NODATA, use NODATA */ if (_param->band.hasnodata[i]) value = _param->band.nodataval[i]; /* no NODATA, use min possible value */ else value = _param->band.minval[i]; inextent = 0; isnodata = 1; } /* add pixel to neighborhood */ status++; if (status > 1) npixels = (rt_pixel) rtrealloc(npixels, sizeof(struct rt_pixel_t) * status); else npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t)); if (npixels == NULL) { rterror("rt_raster_iterator: Could not reallocate memory for neighborhood"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } npixels[status - 1].x = x; npixels[status - 1].y = y; npixels[status - 1].nodata = 1; npixels[status - 1].value = value; /* set nodata flag */ if ((!_param->band.hasnodata[i] && inextent) || !isnodata) { npixels[status - 1].nodata = 0; } RASTER_DEBUGF(4, "value, nodata: %f, %d", value, npixels[status - 1].nodata); /* convert set of rt_pixel to 2D array */ status = rt_pixel_set_to_array( npixels, status,mask, x, y, distancex, distancey, &(_param->arg->values[i]), &(_param->arg->nodata[i]), NULL, NULL ); rtdealloc(npixels); if (status != ES_NONE) { rterror("rt_raster_iterator: Could not create 2D array of neighborhood"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } } /* callback */ RASTER_DEBUG(4, "calling callback function"); value = 0; nodata = 0; status = callback(_param->arg, userarg, &value, &nodata); /* free memory from callback */ _rti_iterator_arg_callback_clean(_param); /* handle callback status */ if (status == 0) { rterror("rt_raster_iterator: Callback function returned an error"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } /* burn value to pixel */ status = 0; if (!nodata) { status = rt_band_set_pixel(rtnband, _x, _y, value, NULL); RASTER_DEBUGF(4, "burning pixel (%d, %d) with value: %f", _x, _y, value); } else if (!hasnodata) { status = rt_band_set_pixel(rtnband, _x, _y, minval, NULL); RASTER_DEBUGF(4, "burning pixel (%d, %d) with minval: %f", _x, _y, minval); } else { RASTER_DEBUGF(4, "NOT burning pixel (%d, %d)", _x, _y); } if (status != ES_NONE) { rterror("rt_raster_iterator: Could not set pixel value"); _rti_iterator_arg_destroy(_param); rt_band_destroy(rtnband); rt_raster_destroy(rtnrast); return ES_ERROR; } } } /* lots of cleanup */ _rti_iterator_arg_destroy(_param); *rtnraster = rtnrast; return ES_NONE; }
static int _rti_iterator_arg_populate( _rti_iterator_arg _param, rt_iterator itrset, uint16_t itrcount, uint16_t distancex, uint16_t distancey, int *allnull, int *allempty ) { int i = 0; int hasband = 0; _param->count = itrcount; _param->distance.x = distancex; _param->distance.y = distancey; _param->dimension.columns = distancex * 2 + 1; _param->dimension.rows = distancey * 2 + 1; /* allocate memory for children */ _param->raster = rtalloc(sizeof(rt_raster) * itrcount); _param->isempty = rtalloc(sizeof(int) * itrcount); _param->width = rtalloc(sizeof(int) * itrcount); _param->height = rtalloc(sizeof(int) * itrcount); _param->offset = rtalloc(sizeof(double *) * itrcount); _param->band.rtband = rtalloc(sizeof(rt_band) * itrcount); _param->band.hasnodata = rtalloc(sizeof(int) * itrcount); _param->band.isnodata = rtalloc(sizeof(int) * itrcount); _param->band.nodataval = rtalloc(sizeof(double) * itrcount); _param->band.minval = rtalloc(sizeof(double) * itrcount); if ( _param->raster == NULL || _param->isempty == NULL || _param->width == NULL || _param->height == NULL || _param->offset == NULL || _param->band.rtband == NULL || _param->band.hasnodata == NULL || _param->band.isnodata == NULL || _param->band.nodataval == NULL || _param->band.minval == NULL ) { rterror("_rti_iterator_arg_populate: Could not allocate memory for children of _rti_iterator_arg"); return 0; } *allnull = 0; *allempty = 0; /* check input rasters not empty, band # is valid copy raster pointers and set flags */ for (i = 0; i < itrcount; i++) { /* initialize elements */ _param->raster[i] = NULL; _param->isempty[i] = 0; _param->width[i] = 0; _param->height[i] = 0; _param->offset[i] = NULL; _param->band.rtband[i] = NULL; _param->band.hasnodata[i] = 0; _param->band.isnodata[i] = 0; _param->band.nodataval[i] = 0; _param->band.minval[i] = 0; /* set isempty */ if (itrset[i].raster == NULL) { _param->isempty[i] = 1; (*allnull)++; (*allempty)++; continue; } else if (rt_raster_is_empty(itrset[i].raster)) { _param->isempty[i] = 1; (*allempty)++; continue; } /* check band number */ hasband = rt_raster_has_band(itrset[i].raster, itrset[i].nband); if (!hasband) { if (!itrset[i].nbnodata) { rterror("_rti_iterator_arg_populate: Band %d not found for raster %d", itrset[i].nband, i); return 0; } else { RASTER_DEBUGF(4, "Band %d not found for raster %d. Using NODATA", itrset[i].nband, i); } } _param->raster[i] = itrset[i].raster; if (hasband) { _param->band.rtband[i] = rt_raster_get_band(itrset[i].raster, itrset[i].nband); if (_param->band.rtband[i] == NULL) { rterror("_rti_iterator_arg_populate: Could not get band %d for raster %d", itrset[i].nband, i); return 0; } /* hasnodata */ _param->band.hasnodata[i] = rt_band_get_hasnodata_flag(_param->band.rtband[i]); /* hasnodata = TRUE */ if (_param->band.hasnodata[i]) { /* nodataval */ rt_band_get_nodata(_param->band.rtband[i], &(_param->band.nodataval[i])); /* isnodata */ _param->band.isnodata[i] = rt_band_get_isnodata_flag(_param->band.rtband[i]); } /* hasnodata = FALSE */ else { /* minval */ _param->band.minval[i] = rt_band_get_min_value(_param->band.rtband[i]); } } /* width, height */ _param->width[i] = rt_raster_get_width(_param->raster[i]); _param->height[i] = rt_raster_get_height(_param->raster[i]); /* init offset */ _param->offset[i] = rtalloc(sizeof(double) * 2); if (_param->offset[i] == NULL) { rterror("_rti_iterator_arg_populate: Could not allocate memory for offsets"); return 0; } } return 1; }
/** * Returns new band with values reclassified * * @param srcband : the band who's values will be reclassified * @param pixtype : pixel type of the new band * @param hasnodata : indicates if the band has a nodata value * @param nodataval : nodata value for the new band * @param exprset : array of rt_reclassexpr structs * @param exprcount : number of elements in expr * * @return a new rt_band or NULL on error */ rt_band rt_band_reclass( rt_band srcband, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, rt_reclassexpr *exprset, int exprcount ) { rt_band band = NULL; uint32_t width = 0; uint32_t height = 0; int numval = 0; int memsize = 0; void *mem = NULL; uint32_t src_hasnodata = 0; double src_nodataval = 0.0; int isnodata = 0; int rtn; uint32_t x; uint32_t y; int i; double or = 0; double ov = 0; double nr = 0; double nv = 0; int do_nv = 0; rt_reclassexpr expr = NULL; assert(NULL != srcband); assert(NULL != exprset && exprcount > 0); RASTER_DEBUGF(4, "exprcount = %d", exprcount); RASTER_DEBUGF(4, "exprset @ %p", exprset); /* source nodata */ src_hasnodata = rt_band_get_hasnodata_flag(srcband); if (src_hasnodata) rt_band_get_nodata(srcband, &src_nodataval); /* size of memory block to allocate */ width = rt_band_get_width(srcband); height = rt_band_get_height(srcband); numval = width * height; memsize = rt_pixtype_size(pixtype) * numval; mem = (int *) rtalloc(memsize); if (!mem) { rterror("rt_band_reclass: Could not allocate memory for band"); return 0; } /* initialize to zero */ if (!hasnodata) { memset(mem, 0, memsize); } /* initialize to nodataval */ else { int32_t checkvalint = 0; uint32_t checkvaluint = 0; double checkvaldouble = 0; float checkvalfloat = 0; switch (pixtype) { case PT_1BB: { uint8_t *ptr = mem; uint8_t clamped_initval = rt_util_clamp_to_1BB(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_2BUI: { uint8_t *ptr = mem; uint8_t clamped_initval = rt_util_clamp_to_2BUI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_4BUI: { uint8_t *ptr = mem; uint8_t clamped_initval = rt_util_clamp_to_4BUI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_8BSI: { int8_t *ptr = mem; int8_t clamped_initval = rt_util_clamp_to_8BSI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_8BUI: { uint8_t *ptr = mem; uint8_t clamped_initval = rt_util_clamp_to_8BUI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_16BSI: { int16_t *ptr = mem; int16_t clamped_initval = rt_util_clamp_to_16BSI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_16BUI: { uint16_t *ptr = mem; uint16_t clamped_initval = rt_util_clamp_to_16BUI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_32BSI: { int32_t *ptr = mem; int32_t clamped_initval = rt_util_clamp_to_32BSI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalint = ptr[0]; break; } case PT_32BUI: { uint32_t *ptr = mem; uint32_t clamped_initval = rt_util_clamp_to_32BUI(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvaluint = ptr[0]; break; } case PT_32BF: { float *ptr = mem; float clamped_initval = rt_util_clamp_to_32F(nodataval); for (i = 0; i < numval; i++) ptr[i] = clamped_initval; checkvalfloat = ptr[0]; break; } case PT_64BF: { double *ptr = mem; for (i = 0; i < numval; i++) ptr[i] = nodataval; checkvaldouble = ptr[0]; break; } default: { rterror("rt_band_reclass: Unknown pixeltype %d", pixtype); rtdealloc(mem); return 0; } } /* Overflow checking */ rt_util_dbl_trunc_warning( nodataval, checkvalint, checkvaluint, checkvalfloat, checkvaldouble, pixtype ); } RASTER_DEBUGF(3, "rt_band_reclass: width = %d height = %d", width, height); band = rt_band_new_inline(width, height, pixtype, hasnodata, nodataval, mem); if (!band) { rterror("rt_band_reclass: Could not create new band"); rtdealloc(mem); return 0; } rt_band_set_ownsdata_flag(band, 1); /* we DO own this data!!! */ RASTER_DEBUGF(3, "rt_band_reclass: new band @ %p", band); for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { rtn = rt_band_get_pixel(srcband, x, y, &ov, &isnodata); /* error getting value, skip */ if (rtn != ES_NONE) { RASTER_DEBUGF(3, "Cannot get value at %d, %d", x, y); continue; } RASTER_DEBUGF(4, "(x, y, ov, isnodata) = (%d, %d, %f, %d)", x, y, ov, isnodata); do { do_nv = 0; /* no data*/ if (hasnodata && isnodata) { do_nv = 1; break; } for (i = 0; i < exprcount; i++) { expr = exprset[i]; /* ov matches min and max*/ if ( FLT_EQ(expr->src.min, ov) && FLT_EQ(expr->src.max, ov) ) { do_nv = 1; break; } /* process min */ if (( expr->src.exc_min && ( expr->src.min > ov || FLT_EQ(expr->src.min, ov) )) || ( expr->src.inc_min && ( expr->src.min < ov || FLT_EQ(expr->src.min, ov) )) || ( expr->src.min < ov )) { /* process max */ if (( expr->src.exc_max && ( ov > expr->src.max || FLT_EQ(expr->src.max, ov) )) || ( expr->src.inc_max && ( ov < expr->src.max || FLT_EQ(expr->src.max, ov) )) || ( ov < expr->src.max )) { do_nv = 1; break; } } } } while (0); /* no expression matched, do not continue */ if (!do_nv) continue; RASTER_DEBUGF(3, "Using exprset[%d] unless NODATA", i); /* converting a value from one range to another range OldRange = (OldMax - OldMin) NewRange = (NewMax - NewMin) NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin */ /* NODATA */ if (hasnodata && isnodata) { nv = nodataval; } /* "src" min and max is the same, prevent division by zero set nv to "dst" min, which should be the same as "dst" max */ else if (FLT_EQ(expr->src.max, expr->src.min)) { nv = expr->dst.min; } else { or = expr->src.max - expr->src.min; nr = expr->dst.max - expr->dst.min; nv = (((ov - expr->src.min) * nr) / or) + expr->dst.min; /* if dst range is from high to low */ if (expr->dst.min > expr->dst.max) { if (nv > expr->dst.min) nv = expr->dst.min; else if (nv < expr->dst.max) nv = expr->dst.max; } /* if dst range is from low to high */ else { if (nv < expr->dst.min) nv = expr->dst.min; else if (nv > expr->dst.max) nv = expr->dst.max; } } /* round the value for integers */ switch (pixtype) { case PT_1BB: case PT_2BUI: case PT_4BUI: case PT_8BSI: case PT_8BUI: case PT_16BSI: case PT_16BUI: case PT_32BSI: case PT_32BUI: nv = round(nv); break; default: break; } RASTER_DEBUGF(4, "(%d, %d) ov: %f or: %f - %f nr: %f - %f nv: %f" , x , y , ov , (NULL != expr) ? expr->src.min : 0 , (NULL != expr) ? expr->src.max : 0 , (NULL != expr) ? expr->dst.min : 0 , (NULL != expr) ? expr->dst.max : 0 , nv ); if (rt_band_set_pixel(band, x, y, nv, NULL) != ES_NONE) { rterror("rt_band_reclass: Could not assign value to new band"); rt_band_destroy(band); rtdealloc(mem); return 0; } expr = NULL; } } return band; }
/** * Returns a new raster with up to four 8BUI bands (RGBA) from * applying a colormap to the user-specified band of the * input raster. * * @param raster: input raster * @param nband: 0-based index of the band to process with colormap * @param colormap: rt_colormap object of colormap to apply to band * * @return new raster or NULL on error */ rt_raster rt_raster_colormap( rt_raster raster, int nband, rt_colormap colormap ) { _rti_colormap_arg arg = NULL; rt_raster rtnraster = NULL; rt_band band = NULL; int i = 0; int j = 0; int k = 0; assert(colormap != NULL); /* empty raster */ if (rt_raster_is_empty(raster)) return NULL; /* no colormap entries */ if (colormap->nentry < 1) { rterror("rt_raster_colormap: colormap must have at least one entry"); return NULL; } /* nband is valid */ if (!rt_raster_has_band(raster, nband)) { rterror("rt_raster_colormap: raster has no band at index %d", nband); return NULL; } band = rt_raster_get_band(raster, nband); if (band == NULL) { rterror("rt_raster_colormap: Could not get band at index %d", nband); return NULL; } /* init internal variables */ arg = _rti_colormap_arg_init(raster); if (arg == NULL) { rterror("rt_raster_colormap: Could not initialize internal variables"); return NULL; } /* handle NODATA */ if (rt_band_get_hasnodata_flag(band)) { arg->hasnodata = 1; rt_band_get_nodata(band, &(arg->nodataval)); } /* # of colors */ if (colormap->ncolor < 1) { rterror("rt_raster_colormap: At least one color must be provided"); _rti_colormap_arg_destroy(arg); return NULL; } else if (colormap->ncolor > 4) { rtinfo("More than four colors indicated. Using only the first four colors"); colormap->ncolor = 4; } /* find non-NODATA entries */ arg->npos = 0; arg->pos = rtalloc(sizeof(uint16_t) * colormap->nentry); if (arg->pos == NULL) { rterror("rt_raster_colormap: Could not allocate memory for valid entries"); _rti_colormap_arg_destroy(arg); return NULL; } for (i = 0, j = 0; i < colormap->nentry; i++) { /* special handling for NODATA entries */ if (colormap->entry[i].isnodata) { /* first NODATA entry found, use it */ if (arg->nodataentry == NULL) arg->nodataentry = &(colormap->entry[i]); else rtwarn("More than one colormap entry found for NODATA value. Only using first NOTDATA entry"); continue; } (arg->npos)++; arg->pos[j++] = i; } /* INTERPOLATE and only one non-NODATA entry */ if (colormap->method == CM_INTERPOLATE && arg->npos < 2) { rtinfo("Method INTERPOLATE requires at least two non-NODATA colormap entries. Using NEAREST instead"); colormap->method = CM_NEAREST; } /* NODATA entry but band has no NODATA value */ if (!arg->hasnodata && arg->nodataentry != NULL) { rtinfo("Band at index %d has no NODATA value. Ignoring NODATA entry", nband); arg->nodataentry = NULL; } /* allocate expr */ arg->nexpr = arg->npos; /* INTERPOLATE needs one less than the number of entries */ if (colormap->method == CM_INTERPOLATE) arg->nexpr -= 1; /* EXACT requires a no matching expression */ else if (colormap->method == CM_EXACT) arg->nexpr += 1; /* NODATA entry exists, add expression */ if (arg->nodataentry != NULL) arg->nexpr += 1; arg->expr = rtalloc(sizeof(rt_reclassexpr) * arg->nexpr); if (arg->expr == NULL) { rterror("rt_raster_colormap: Could not allocate memory for reclass expressions"); _rti_colormap_arg_destroy(arg); return NULL; } RASTER_DEBUGF(4, "nexpr = %d", arg->nexpr); RASTER_DEBUGF(4, "expr @ %p", arg->expr); for (i = 0; i < arg->nexpr; i++) { arg->expr[i] = rtalloc(sizeof(struct rt_reclassexpr_t)); if (arg->expr[i] == NULL) { rterror("rt_raster_colormap: Could not allocate memory for reclass expression"); _rti_colormap_arg_destroy(arg); return NULL; } } /* reclassify bands */ /* by # of colors */ for (i = 0; i < colormap->ncolor; i++) { k = 0; /* handle NODATA entry first */ if (arg->nodataentry != NULL) { arg->expr[k]->src.min = arg->nodataentry->value; arg->expr[k]->src.max = arg->nodataentry->value; arg->expr[k]->src.inc_min = 1; arg->expr[k]->src.inc_max = 1; arg->expr[k]->src.exc_min = 0; arg->expr[k]->src.exc_max = 0; arg->expr[k]->dst.min = arg->nodataentry->color[i]; arg->expr[k]->dst.max = arg->nodataentry->color[i]; arg->expr[k]->dst.inc_min = 1; arg->expr[k]->dst.inc_max = 1; arg->expr[k]->dst.exc_min = 0; arg->expr[k]->dst.exc_max = 0; RASTER_DEBUGF(4, "NODATA expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)", k, arg->expr[k]->src.min, arg->expr[k]->src.max, arg->expr[k]->src.inc_min, arg->expr[k]->src.inc_max, arg->expr[k]->src.exc_min, arg->expr[k]->src.exc_max ); RASTER_DEBUGF(4, "NODATA expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)", k, arg->expr[k]->dst.min, arg->expr[k]->dst.max, arg->expr[k]->dst.inc_min, arg->expr[k]->dst.inc_max, arg->expr[k]->dst.exc_min, arg->expr[k]->dst.exc_max ); k++; } /* by non-NODATA entry */ for (j = 0; j < arg->npos; j++) { if (colormap->method == CM_INTERPOLATE) { if (j == arg->npos - 1) continue; arg->expr[k]->src.min = colormap->entry[arg->pos[j + 1]].value; arg->expr[k]->src.inc_min = 1; arg->expr[k]->src.exc_min = 0; arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value; arg->expr[k]->src.inc_max = 1; arg->expr[k]->src.exc_max = 0; arg->expr[k]->dst.min = colormap->entry[arg->pos[j + 1]].color[i]; arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i]; arg->expr[k]->dst.inc_min = 1; arg->expr[k]->dst.exc_min = 0; arg->expr[k]->dst.inc_max = 1; arg->expr[k]->dst.exc_max = 0; } else if (colormap->method == CM_NEAREST) { /* NOT last entry */ if (j != arg->npos - 1) { arg->expr[k]->src.min = ((colormap->entry[arg->pos[j]].value - colormap->entry[arg->pos[j + 1]].value) / 2.) + colormap->entry[arg->pos[j + 1]].value; arg->expr[k]->src.inc_min = 0; arg->expr[k]->src.exc_min = 0; } /* last entry */ else { arg->expr[k]->src.min = colormap->entry[arg->pos[j]].value; arg->expr[k]->src.inc_min = 1; arg->expr[k]->src.exc_min = 1; } /* NOT first entry */ if (j > 0) { arg->expr[k]->src.max = arg->expr[k - 1]->src.min; arg->expr[k]->src.inc_max = 1; arg->expr[k]->src.exc_max = 0; } /* first entry */ else { arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value; arg->expr[k]->src.inc_max = 1; arg->expr[k]->src.exc_max = 1; } arg->expr[k]->dst.min = colormap->entry[arg->pos[j]].color[i]; arg->expr[k]->dst.inc_min = 1; arg->expr[k]->dst.exc_min = 0; arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i]; arg->expr[k]->dst.inc_max = 1; arg->expr[k]->dst.exc_max = 0; } else if (colormap->method == CM_EXACT) { arg->expr[k]->src.min = colormap->entry[arg->pos[j]].value; arg->expr[k]->src.inc_min = 1; arg->expr[k]->src.exc_min = 0; arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value; arg->expr[k]->src.inc_max = 1; arg->expr[k]->src.exc_max = 0; arg->expr[k]->dst.min = colormap->entry[arg->pos[j]].color[i]; arg->expr[k]->dst.inc_min = 1; arg->expr[k]->dst.exc_min = 0; arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i]; arg->expr[k]->dst.inc_max = 1; arg->expr[k]->dst.exc_max = 0; } RASTER_DEBUGF(4, "expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)", k, arg->expr[k]->src.min, arg->expr[k]->src.max, arg->expr[k]->src.inc_min, arg->expr[k]->src.inc_max, arg->expr[k]->src.exc_min, arg->expr[k]->src.exc_max ); RASTER_DEBUGF(4, "expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)", k, arg->expr[k]->dst.min, arg->expr[k]->dst.max, arg->expr[k]->dst.inc_min, arg->expr[k]->dst.inc_max, arg->expr[k]->dst.exc_min, arg->expr[k]->dst.exc_max ); k++; } /* EXACT has one last expression for catching all uncaught values */ if (colormap->method == CM_EXACT) { arg->expr[k]->src.min = 0; arg->expr[k]->src.inc_min = 1; arg->expr[k]->src.exc_min = 1; arg->expr[k]->src.max = 0; arg->expr[k]->src.inc_max = 1; arg->expr[k]->src.exc_max = 1; arg->expr[k]->dst.min = 0; arg->expr[k]->dst.inc_min = 1; arg->expr[k]->dst.exc_min = 0; arg->expr[k]->dst.max = 0; arg->expr[k]->dst.inc_max = 1; arg->expr[k]->dst.exc_max = 0; RASTER_DEBUGF(4, "expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)", k, arg->expr[k]->src.min, arg->expr[k]->src.max, arg->expr[k]->src.inc_min, arg->expr[k]->src.inc_max, arg->expr[k]->src.exc_min, arg->expr[k]->src.exc_max ); RASTER_DEBUGF(4, "expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)", k, arg->expr[k]->dst.min, arg->expr[k]->dst.max, arg->expr[k]->dst.inc_min, arg->expr[k]->dst.inc_max, arg->expr[k]->dst.exc_min, arg->expr[k]->dst.exc_max ); k++; } /* call rt_band_reclass */ arg->band = rt_band_reclass(band, PT_8BUI, 0, 0, arg->expr, arg->nexpr); if (arg->band == NULL) { rterror("rt_raster_colormap: Could not reclassify band"); _rti_colormap_arg_destroy(arg); return NULL; } /* add reclassified band to raster */ if (rt_raster_add_band(arg->raster, arg->band, rt_raster_get_num_bands(arg->raster)) < 0) { rterror("rt_raster_colormap: Could not add reclassified band to output raster"); _rti_colormap_arg_destroy(arg); return NULL; } } rtnraster = arg->raster; arg->raster = NULL; _rti_colormap_arg_destroy(arg); return rtnraster; }
static int tcp_connect_oncpu(struct tcpcb *tp, int flags, struct mbuf *m, struct sockaddr_in *sin, struct sockaddr_in *if_sin) { struct inpcb *inp = tp->t_inpcb, *oinp; struct socket *so = inp->inp_socket; struct route *ro = &inp->inp_route; oinp = in_pcblookup_hash(&tcbinfo[mycpu->gd_cpuid], sin->sin_addr, sin->sin_port, (inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr : if_sin->sin_addr), inp->inp_lport, 0, NULL); if (oinp != NULL) { m_freem(m); return (EADDRINUSE); } if (inp->inp_laddr.s_addr == INADDR_ANY) inp->inp_laddr = if_sin->sin_addr; inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; inp->inp_cpcbinfo = &tcbinfo[mycpu->gd_cpuid]; in_pcbinsconnhash(inp); /* * We are now on the inpcb's owner CPU, if the cached route was * freed because the rtentry's owner CPU is not the current CPU * (e.g. in tcp_connect()), then we try to reallocate it here with * the hope that a rtentry may be cloned from a RTF_PRCLONING * rtentry. */ if (!(inp->inp_socket->so_options & SO_DONTROUTE) && /*XXX*/ ro->ro_rt == NULL) { bzero(&ro->ro_dst, sizeof(struct sockaddr_in)); ro->ro_dst.sa_family = AF_INET; ro->ro_dst.sa_len = sizeof(struct sockaddr_in); ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sin->sin_addr; rtalloc(ro); } /* * Now that no more errors can occur, change the protocol processing * port to the current thread (which is the correct thread). * * Create TCP timer message now; we are on the tcpcb's owner * CPU/thread. */ tcp_create_timermsg(tp, &curthread->td_msgport); /* * Compute window scaling to request. Use a larger scaling then * needed for the initial receive buffer in case the receive buffer * gets expanded. */ if (tp->request_r_scale < TCP_MIN_WINSHIFT) tp->request_r_scale = TCP_MIN_WINSHIFT; while (tp->request_r_scale < TCP_MAX_WINSHIFT && (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.ssb_hiwat ) { tp->request_r_scale++; } soisconnecting(so); tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tcp_callout_reset(tp, tp->tt_keep, tcp_keepinit, tcp_timer_keep); tp->iss = tcp_new_isn(tp); tcp_sendseqinit(tp); if (m) { ssb_appendstream(&so->so_snd, m); m = NULL; if (flags & PRUS_OOB) tp->snd_up = tp->snd_una + so->so_snd.ssb_cc; } /* * Close the send side of the connection after * the data is sent if flagged. */ if ((flags & (PRUS_OOB|PRUS_EOF)) == PRUS_EOF) { socantsendmore(so); tp = tcp_usrclosed(tp); } return (tcp_output(tp)); }
int ddp_route( struct mbuf *m, struct route *ro) { struct sockaddr_at gate; struct elaphdr *elh; struct mbuf *m0; struct at_ifaddr *aa = NULL; struct ifnet *ifp = NULL; u_short net; #if 0 /* Check for net zero, node zero ("myself") */ if (satosat(&ro->ro_dst)->sat_addr.s_net == ATADDR_ANYNET && satosat(&ro->ro_dst)->sat_addr.s_node == ATADDR_ANYNODE) { /* Find the loopback interface */ } #endif /* * if we have a route, find the ifa that refers to this route. * I.e The ifa used to get to the gateway. */ if ( (ro->ro_rt == NULL) || ( ro->ro_rt->rt_ifa == NULL ) || ( (ifp = ro->ro_rt->rt_ifa->ifa_ifp) == NULL )) { rtalloc(ro); } if ( (ro->ro_rt != NULL) && ( ro->ro_rt->rt_ifa ) && ( ifp = ro->ro_rt->rt_ifa->ifa_ifp )) { net = ntohs(satosat(ro->ro_rt->rt_gateway)->sat_addr.s_net); for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { if (((net == 0) || (aa->aa_ifp == ifp)) && net >= ntohs( aa->aa_firstnet ) && net <= ntohs( aa->aa_lastnet )) { break; } } } else { m_freem( m ); #ifdef NETATALK_DEBUG if (ro->ro_rt == NULL) printf ("ddp_route: no ro_rt.\n"); else if (ro->ro_rt->rt_ifa == NULL) printf ("ddp_route: no ro_rt->rt_ifa\n"); else printf ("ddp_route: no ro_rt->rt_ifa->ifa_ifp\n"); #endif return( ENETUNREACH ); } if ( aa == NULL ) { #ifdef NETATALK_DEBUG printf( "ddp_route: no atalk address found for %s%d\n", ifp->if_name, ifp->if_unit); #endif m_freem( m ); return( ENETUNREACH ); } /* * if the destination address is on a directly attached node use that, * else use the official gateway. */ if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >= ntohs( aa->aa_firstnet ) && ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <= ntohs( aa->aa_lastnet )) { gate = *satosat( &ro->ro_dst ); } else { gate = *satosat( ro->ro_rt->rt_gateway ); } /* * There are several places in the kernel where data is added to * an mbuf without ensuring that the mbuf pointer is aligned. * This is bad for transition routing, since phase 1 and phase 2 * packets end up poorly aligned due to the three byte elap header. */ if ( !(aa->aa_flags & AFA_PHASE2) ) { MGET( m0, M_TRYWAIT, MT_HEADER ); if ( m0 == 0 ) { m_freem( m ); printf("ddp_route: no buffers\n"); return( ENOBUFS ); } #ifdef MAC mac_create_mbuf_from_mbuf(m, m0); #endif m0->m_next = m; /* XXX perhaps we ought to align the header? */ m0->m_len = SZ_ELAPHDR; m = m0; elh = mtod( m, struct elaphdr *); elh->el_snode = satosat( &aa->aa_addr )->sat_addr.s_node; elh->el_type = ELAP_DDPEXTEND; elh->el_dnode = gate.sat_addr.s_node; }
/* * Fragment input * NOTE: this function is called with the inet6_domain_mutex held from ip6_input. * inet6_domain_mutex is protecting he frag6 queue manipulation. */ int frag6_input(struct mbuf **mp, int *offp, int proto) { #pragma unused(proto) struct mbuf *m = *mp, *t; struct ip6_hdr *ip6; struct ip6_frag *ip6f; struct ip6q *q6; struct ip6asfrag *af6, *ip6af, *af6dwn; int offset = *offp, nxt, i, next; int first_frag = 0; int fragoff, frgpartlen; /* must be larger than u_int16_t */ struct ifnet *dstifp; struct ifaddr *ifa = NULL; u_int8_t ecn, ecn0; #ifdef IN6_IFSTAT_STRICT struct route_in6 ro; struct sockaddr_in6 *dst; #endif /* Expect 32-bit aligned data pointer on strict-align platforms */ MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); ip6 = mtod(m, struct ip6_hdr *); #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), return IPPROTO_DONE); ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset); #else IP6_EXTHDR_GET(ip6f, struct ip6_frag *, m, offset, sizeof(*ip6f)); if (ip6f == NULL) return IPPROTO_DONE; #endif dstifp = NULL; #ifdef IN6_IFSTAT_STRICT /* find the destination interface of the packet. */ bzero(&ro, sizeof (ro)); dst = (struct sockaddr_in6 *)&ro.ro_dst; dst->sin6_family = AF_INET6; dst->sin6_len = sizeof (struct sockaddr_in6); dst->sin6_addr = ip6->ip6_dst; rtalloc((struct route *)&ro); if (ro.ro_rt != NULL) { RT_LOCK(ro.ro_rt); if ((ifa = ro.ro_rt->rt_ifa) != NULL) { IFA_ADDREF(ifa); dstifp = ((struct in6_ifaddr *)ro.ro_rt->rt_ifa)->ia_ifp; } RT_UNLOCK(ro.ro_rt); rtfree(ro.ro_rt); ro.ro_rt = NULL; } #else /* we are violating the spec, this is not the destination interface */ if ((m->m_flags & M_PKTHDR) != 0) dstifp = m->m_pkthdr.rcvif; #endif /* jumbo payload can't contain a fragment header */ if (ip6->ip6_plen == 0) { icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset); in6_ifstat_inc(dstifp, ifs6_reass_fail); if (ifa != NULL) IFA_REMREF(ifa); return IPPROTO_DONE; } /* * check whether fragment packet's fragment length is * multiple of 8 octets. * sizeof(struct ip6_frag) == 8 * sizeof(struct ip6_hdr) = 40 */ if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) && (((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) { icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offsetof(struct ip6_hdr, ip6_plen)); in6_ifstat_inc(dstifp, ifs6_reass_fail); if (ifa != NULL) IFA_REMREF(ifa); return IPPROTO_DONE; } ip6stat.ip6s_fragments++; in6_ifstat_inc(dstifp, ifs6_reass_reqd); /* offset now points to data portion */ offset += sizeof(struct ip6_frag); frag6_doing_reass = 1; /* * Enforce upper bound on number of fragments. * If maxfrag is 0, never accept fragments. * If maxfrag is -1, accept all fragments without limitation. */ if (ip6_maxfrags < 0) ; else if (frag6_nfrags >= (u_int)ip6_maxfrags) goto dropfrag; for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next) if (ip6f->ip6f_ident == q6->ip6q_ident && IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) && IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)) break; if (q6 == &ip6q) { /* * the first fragment to arrive, create a reassembly queue. */ first_frag = 1; /* * Enforce upper bound on number of fragmented packets * for which we attempt reassembly; * If maxfrag is 0, never accept fragments. * If maxfrag is -1, accept all fragments without limitation. */ if (ip6_maxfragpackets < 0) ; else if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) goto dropfrag; frag6_nfragpackets++; q6 = (struct ip6q *)_MALLOC(sizeof(struct ip6q), M_FTABLE, M_DONTWAIT); if (q6 == NULL) goto dropfrag; bzero(q6, sizeof(*q6)); frag6_insque(q6, &ip6q); /* ip6q_nxt will be filled afterwards, from 1st fragment */ q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6; #ifdef notyet q6->ip6q_nxtp = (u_char *)nxtp; #endif q6->ip6q_ident = ip6f->ip6f_ident; q6->ip6q_ttl = IPV6_FRAGTTL; q6->ip6q_src = ip6->ip6_src; q6->ip6q_dst = ip6->ip6_dst; q6->ip6q_ecn = (ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK; q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */ q6->ip6q_nfrag = 0; }
/* * Connect from a socket to a specified address. * Both address and port must be specified in argument slpx. * If don't have a local address for this socket yet, * then pick one. */ int Lpx_PCB_connect( struct lpxpcb *lpxp, struct sockaddr *nam, struct proc *td ) { struct lpx_ifaddr *ia = NULL; register struct sockaddr_lpx *slpx = (struct sockaddr_lpx *)nam; register struct lpx_addr *dst; register struct route *ro; struct ifnet *ifp; struct lpx_addr laddr; DEBUG_CALL(4, ("Lpx_PCB_connect\n")); if (nam == NULL) { return(EINVAL); } DEBUG_CALL(2, ("slpx->sipx_addr.x_net = %x\n", slpx->sipx_addr.x_net)); if (slpx->slpx_family != AF_LPX) return (EAFNOSUPPORT); if (slpx->slpx_port == 0 || lpx_nullhost(slpx->sipx_addr)) return (EADDRNOTAVAIL); /* * If we haven't bound which network number to use as ours, * we will use the number of the outgoing interface. * This depends on having done a routing lookup, which * we will probably have to do anyway, so we might * as well do it now. On the other hand if we are * sending to multiple destinations we may have already * done the lookup, so see if we can use the route * from before. In any case, we only * chose a port number once, even if sending to multiple * destinations. */ ro = &lpxp->lpxp_route; dst = &satolpx_addr(ro->ro_dst); if (lpxp->lpxp_socket->so_options & SO_DONTROUTE) goto flush; if (!lpx_neteq(lpxp->lpxp_lastdst, slpx->sipx_addr)) goto flush; if (!lpx_hosteq(lpxp->lpxp_lastdst, slpx->sipx_addr)) { if (ro->ro_rt != NULL && !(ro->ro_rt->rt_flags & RTF_HOST)) { /* can patch route to avoid rtalloc */ *dst = slpx->sipx_addr; } else { flush: if (ro->ro_rt != NULL) RTFREE(ro->ro_rt); ro->ro_rt = NULL; } }/* else cached route is ok; do nothing */ lpxp->lpxp_lastdst = slpx->sipx_addr; if ((lpxp->lpxp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_LPX; ro->ro_dst.sa_len = sizeof(ro->ro_dst); *dst = slpx->sipx_addr; dst->x_port = 0; rtalloc(ro); DEBUG_CALL(4, ("Lpx_PCB_connect RO 1\n")); } if (lpx_neteqnn(lpxp->lpxp_laddr.x_net, lpx_zeronet)) { DEBUG_CALL(4, ("Lpx_PCB_connect RO 2\n")); /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ /* * If we found a route, use the address * corresponding to the outgoing interface */ ia = NULL; if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL) for (ia = lpx_ifaddr; ia != NULL; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == NULL) { // u_short fport = slpx->sipx_addr.x_port; //slpx->sipx_addr.x_port = 0; ia = (struct lpx_ifaddr *) ifa_ifwithaddr((struct sockaddr *)&lpxp->lpxp_laddr); //slpx->sipx_addr.x_port = fport; // BUG BUG BUG!!! if (ia == NULL) ia = Lpx_CTL_iaonnetof(&slpx->sipx_addr); if (ia == NULL) ia = lpx_ifaddr; if (ia == NULL) return (EADDRNOTAVAIL); } lpxp->lpxp_laddr.x_net = satolpx_addr(ia->ia_addr).x_net; } if (lpx_nullhost(lpxp->lpxp_laddr)) { DEBUG_CALL(4, ("Lpx_PCB_connect RO 3\n")); /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ /* * If we found a route, use the address * corresponding to the outgoing interface */ ia = NULL; if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL) for (ia = lpx_ifaddr; ia != NULL; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == NULL) { u_short fport = slpx->sipx_addr.x_port; slpx->sipx_addr.x_port = 0; ia = (struct lpx_ifaddr *) ifa_ifwithdstaddr((struct sockaddr *)slpx); slpx->sipx_addr.x_port = fport; // BUG BUG BUG!!! if (ia == NULL) ia = Lpx_CTL_iaonnetof(&slpx->sipx_addr); if (ia == NULL) ia = lpx_ifaddr; if (ia == NULL) return (EADDRNOTAVAIL); } lpxp->lpxp_laddr.x_host = satolpx_addr(ia->ia_addr).x_host; } DEBUG_CALL(4, ("Lpx_PCB_connect: 4.\n")); laddr.x_port = lpxp->lpxp_lport; if (Lpx_PCB_lookup(&slpx->sipx_addr, &laddr, 0)) return (EADDRINUSE); if (lpxp->lpxp_lport == 0) Lpx_PCB_bind(lpxp, (struct sockaddr *)NULL, td); /* XXX just leave it zero if we can't find a route */ lpxp->lpxp_faddr = slpx->sipx_addr; /* Includes lpxp->lpxp_fport = slpx->slpx_port; */ return (0); }
static int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct proc *p) { struct sockaddr_at *sat = (struct sockaddr_at *)addr; struct route *ro; struct at_ifaddr *aa = 0; struct ifnet *ifp; u_short hintnet = 0, net; if (sat->sat_family != AF_APPLETALK) { return(EAFNOSUPPORT); } /* * Under phase 2, network 0 means "the network". We take "the * network" to mean the network the control block is bound to. * If the control block is not bound, there is an error. */ if ( sat->sat_addr.s_net == ATADDR_ANYNET && sat->sat_addr.s_node != ATADDR_ANYNODE ) { if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) { return( EADDRNOTAVAIL ); } hintnet = ddp->ddp_lsat.sat_addr.s_net; } ro = &ddp->ddp_route; /* * If we've got an old route for this pcb, check that it is valid. * If we've changed our address, we may have an old "good looking" * route here. Attempt to detect it. */ if ( ro->ro_rt ) { if ( hintnet ) { net = hintnet; } else { net = sat->sat_addr.s_net; } aa = 0; if ((ifp = ro->ro_rt->rt_ifp) != NULL) { for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { if ( aa->aa_ifp == ifp && ntohs( net ) >= ntohs( aa->aa_firstnet ) && ntohs( net ) <= ntohs( aa->aa_lastnet )) { break; } } } if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net != ( hintnet ? hintnet : sat->sat_addr.s_net ) || satosat( &ro->ro_dst )->sat_addr.s_node != sat->sat_addr.s_node )) { RTFREE( ro->ro_rt ); ro->ro_rt = (struct rtentry *)0; } } /* * If we've got no route for this interface, try to find one. */ if ( ro->ro_rt == (struct rtentry *)0 || ro->ro_rt->rt_ifp == (struct ifnet *)0 ) { ro->ro_dst.sa_len = sizeof( struct sockaddr_at ); ro->ro_dst.sa_family = AF_APPLETALK; if ( hintnet ) { satosat( &ro->ro_dst )->sat_addr.s_net = hintnet; } else { satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net; } satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node; rtalloc( ro ); } /* * Make sure any route that we have has a valid interface. */ aa = 0; if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) { for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { if ( aa->aa_ifp == ifp ) { break; } } } if ( aa == 0 ) { return( ENETUNREACH ); } ddp->ddp_fsat = *sat; if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) { return(at_pcbsetaddr(ddp, (struct sockaddr *)0, p)); } return( 0 ); }
int ns_output(struct mbuf *m0, ...) { struct route *ro; int flags; struct idp *idp = mtod(m0, struct idp *); struct ifnet *ifp = 0; int error = 0; struct route idproute; struct sockaddr_ns *dst; va_list ap; va_start(ap, m0); ro = va_arg(ap, struct route *); flags = va_arg(ap, int); va_end(ap); if (ns_hold_output) { if (ns_lastout) { (void)m_free(ns_lastout); } ns_lastout = m_copy(m0, 0, (int)M_COPYALL); } /* * Route packet. */ if (ro == 0) { ro = &idproute; bzero((caddr_t)ro, sizeof (*ro)); } dst = satosns(&ro->ro_dst); if (ro->ro_rt == 0) { dst->sns_family = AF_NS; dst->sns_len = sizeof (*dst); dst->sns_addr = idp->idp_dna; dst->sns_addr.x_port = 0; /* * If routing to interface only, * short circuit routing lookup. */ if (flags & NS_ROUTETOIF) { struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); if (ia == 0) { error = ENETUNREACH; goto bad; } ifp = ia->ia_ifp; goto gotif; } rtalloc(ro); } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { /* * The old route has gone away; try for a new one. */ rtfree(ro->ro_rt); ro->ro_rt = NULL; rtalloc(ro); } if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { error = ENETUNREACH; goto bad; } ro->ro_rt->rt_use++; if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) dst = satosns(ro->ro_rt->rt_gateway); gotif: /* * Look for multicast addresses and * and verify user is allowed to send * such a packet. */ if (dst->sns_addr.x_host.c_host[0]&1) { if ((ifp->if_flags & IFF_BROADCAST) == 0) { error = EADDRNOTAVAIL; goto bad; } if ((flags & NS_ALLOWBROADCAST) == 0) { error = EACCES; goto bad; } } if (htons(idp->idp_len) <= ifp->if_mtu) { ns_output_cnt++; if (ns_copy_output) { ns_watch_output(m0, ifp); } error = (*ifp->if_output)(ifp, m0, snstosa(dst), ro->ro_rt); goto done; } else error = EMSGSIZE; bad: if (ns_copy_output) { ns_watch_output(m0, ifp); } m_freem(m0); done: if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) { RTFREE(ro->ro_rt); ro->ro_rt = 0; } return (error); }
static int wdbUdpSockRcvfrom ( WDB_COMM_ID commId, caddr_t addr, uint_t len, struct sockaddr_in *pSockAddr, struct timeval *tv ) { uint_t nBytes; int addrLen = sizeof (struct sockaddr_in); struct fd_set readFds; static struct route theRoute; struct sockaddr_in sockAddr; /* wait for data with a timeout */ FD_ZERO (&readFds); FD_SET (wdbUdpSock, &readFds); if (select (wdbUdpSock + 1, &readFds, NULL, NULL, tv) < 0) { printErr ("wdbUdpSockLib: select failed!\n"); return (0); } if (!FD_ISSET (wdbUdpSock, &readFds)) { return (0); /* select timed out */ } /* read the data */ nBytes = recvfrom (wdbUdpSock, addr, len, 0, (struct sockaddr *)pSockAddr, &addrLen); if (nBytes < 4) return (0); /* * The following is a fix for SPR #4645 (the agent does * not report the correct MTU to the host). We lower * the value of the global variable wdbCommMtu if a packet * arrives via an interface with a smaller MTU. * * XXX This fix has some problems: * 1) it uses rtalloc, which is not an approved interface. * Note: rtalloc doesn't seem to like having the port number * in the socket address. * 2) it assumes all agent packets arrive via the same netif. * 3) it doesn't take into account intermediate MTUs in a WAN. * The right fix for (3) would be to use an MTU-discovey * algorithm (e.g. send larger and larger IP datagrams with the * "don't fragment" flag until an ICMP error is returned). */ if (theRoute.ro_rt == NULL) { sockAddr = *pSockAddr; sockAddr.sin_port = 0; theRoute.ro_dst = * (struct sockaddr *) &sockAddr; rtalloc (&theRoute); if (theRoute.ro_rt != NULL) { if (wdbCommMtu > theRoute.ro_rt->rt_ifp->if_mtu) wdbCommMtu = theRoute.ro_rt->rt_ifp->if_mtu; rtfree (theRoute.ro_rt); } } return (nBytes); }